Другие уже дали хорошие ответы о том, как генерировать код во время выполнения, поэтому я подумал, что расскажу о вашем втором абзаце. У меня есть некоторый опыт в этом, и я просто хочу поделиться уроком, который я извлек из этого опыта.
По крайней мере, я мог бы определить
интерфейс, который им потребуется
реализовать, то они предоставят
«раздел» кода, который реализовал это
интерфейс.
У вас могут быть проблемы, если вы используете interface
в качестве базового типа. Если в будущем вы добавите один новый метод к interface
, все существующие клиентские классы, которые реализуют interface
, теперь станут абстрактными, то есть вы не сможете скомпилировать или создать экземпляр клиентского класса во время выполнения.
У меня была эта проблема, когда пришло время добавить новый метод примерно через 1 год после доставки старого интерфейса и после распространения большого количества «устаревших» данных, которые необходимо было поддерживать. Я закончил тем, что создал новый интерфейс, унаследованный от старого, но этот подход усложнил загрузку и создание экземпляров клиентских классов, потому что я должен был проверить, какой интерфейс был доступен.
Одним из решений, о котором я думал в то время, было вместо этого использовать фактический класс в качестве базового типа, такого как приведенный ниже. Сам класс может быть помечен как абстрактный, но все методы должны быть пустыми виртуальными методами (не абстрактными методами). Затем клиенты могут переопределить нужные им методы, и я могу добавить новые методы в базовый класс, не аннулируя существующий предоставленный клиентом код.
public abstract class BaseClass
{
public virtual void Foo1() { }
public virtual bool Foo2() { return false; }
...
}
Независимо от того, применяется ли эта проблема, вам следует подумать о том, как создать версию интерфейса между вашей кодовой базой и предоставленным клиентом кодом.