Мое решение состоит в том, чтобы переместить инициализацию (из статического конструктора производных классов) в статический конструктор базового класса (который вызывается автоматически перед выполнением моего первого вызова метода CreateFromTargetType
) и с помощью отражения тамизучить производные классы.В производных классах я определил статические методы (TargetType
), которые возвращают конкретные Type
, с которыми они работают.
Ни элегантно, ни компактно, и, конечно, не очень быстро, но это позволяет мне сохранять связь между производным классом (например, SeriesViewForm
) и типом данных, с которым он работает (typeof(Series)
), близко друг к другу (вто же определение класса).
public abstract class CacheableViewForm: Form
{
static Dictionary<Type, Func<CacheableViewForm>> CacheableViewFormConstructors = new Dictionary<Type, Func<CacheableViewForm>>();
static CacheableViewForm()
{
var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach(Assembly assembly in allAssemblies)
{
Type[] cacheableViewFormTypes = assembly.GetExportedTypes().Where(t => typeof(CacheableViewForm).IsAssignableFrom(t) && t != typeof(CacheableViewForm)).ToArray();
foreach (Type cacheableViewFormType in cacheableViewFormTypes)
{
MethodInfo mi = cacheableViewFormType.GetMethod("TargetType");
Type cacheableType = (Type)mi.Invoke(null, null);
Func<CacheableViewForm> ctorDelegate = (() => (CacheableViewForm)(Activator.CreateInstance(cacheableViewFormType)));
CacheableViewFormConstructors[cacheableType] = ctorDelegate;
}
}
}
public static CacheableViewForm CreateFromTargetType(Type cacheableType)
{
return CacheableViewFormConstructors[cacheableType]();
}
}
public class SeriesViewForm: CacheableViewForm
{
public static Type TargetType() {return typeof(Series);}
// ...
}