В некоторых редких ситуациях может потребоваться ограничение на самоссылающиеся типы, но я не уверен, что это одна из них.
Кажется, что вы хотите использовать фабричный (Создать) шаблон, а также заставить эти фабрики возвращать разные конкретные типы.Но в то же время вы говорите, что все эти конкретные типы имеют что-то общее, определенное базовым классом.
Обычный подход заключается в определении общих функций в интерфейсе (как вы предложили IMyInterface) и возврате его из метода Create.Это охватило бы полиморфный аспект конкретных классов.Тогда возникает вопрос, как захватить другие методы, которые реализованы в конкретных типах.Для этого можно просто определить дополнительные интерфейсы, которые охватывают различные кластеры функциональности, реализованные более чем одним из конкретных классов.
В той мере, в которой после этого у вас остались какие-то проблемы с функциональностью, я бы сказал, что обработать их путем приведения будет проще всего - в этот момент функциональность будет уникальной дляодин из конкретных классов.Если вы хотите летать с закрытыми глазами, вы можете использовать «динамический» тип вместо кастинга.
Кроме того, обычно метод Create не определяется в экземплярах объекта, другими словами, обычно объекты не являются их собственными фабриками.Обычно они либо статические, либо в отдельных фабричных классах.В текущей ситуации немного размышлений помогает справиться с тем фактом, что у вас есть несколько производных типов.Существуют различные способы сделать это, кроме того, что я покажу ниже.
Итак… возможно, что-то вроде этого:
public interface ICommonFunctionality
{
void SomethingThatEveryoneCanDo();
// ... other common functionality
}
public interface IAdditionalFunctionality1
{
void SomethingThatAFewCanDo();
// ... other special functionality
}
public interface IAdditionalFunctionality2
{
void SomethingThatOthersCanDo();
// ... other special functionality
}
public class MyClass : ICommonFunctionality
{
static public ICommonFunctionality Create(Type derivedType)
{
if (!typeof(ICommonFunctionality).IsAssignableFrom(derivedType)) { throw new ArgumentException(); }
return derivedType.CreateInstance() as ICommonFunctionality;
}
virtual public void SomethingThatEveryoneCanDo() { /* ... */ }
}
public class MyClass1 : MyClass, IAdditionalFunctionality1
{
public void SomethingThatAFewCanDo() { /* ... */ }
}
public class MyClass2 : MyClass, IAdditionalFunctionality1, IAdditionalFunctionality2
{
public void SomethingThatAFewCanDo() { /* ... */ }
public void SomethingThatOthersCanDo() { /* ... */ }
}
public class MyClass3 : MyClass, IAdditionalFunctionality2
{
public void SomethingThatOthersCanDo() { /* ... */ }
}
public static class TypeHelpers
{
public static object CreateInstance(this Type type, bool required = true)
{
System.Reflection.ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
if (required && ctor == null) { throw new InvalidOperationException("Missing required constructor."); }
return ctor?.Invoke(null);
}
}
PS Я сделал метод базового класса виртуальным, это в значительной степени необязательно в зависимости от вашей ситуации.