我想在派生类中使用静态构造函数来注册对象构造函数lambda,以便在传递某个Type
对象时调用这些类。
由于仅在创建该类的第一个对象之前才调用静态构造函数,但是我想使用静态构造函数的结果来确定要创建哪种对象,因此该机制失败,未找到构造函数lambda
有什么办法吗?
public abstract class Cacheable
{
// ... details do not matter ...
}
public class Series: Cacheable
{
// ... details do not matter ...
}
public abstract class CacheableViewForm
{
static Dictionary<Type, Func<CacheableViewForm>> cacheableViewFormConstructors = new Dictionary<Type, Func<CacheableViewForm>>();
protected static void Register<CacheableViewFormClass, CacheableClass>()
where CacheableViewFormClass: CacheableViewForm, new()
where CacheableClass: Cacheable
{
cacheableViewFormConstructors[typeof(CacheableClass)] = (() => new CacheableViewFormClass());
}
public static CacheableViewForm CreateFromTargetType(Type cacheableType)
{
return cacheableViewFormConstructors[cacheableType]();
}
// ... details do not matter ...
}
public class SeriesViewForm: CacheableViewForm
{
static SeriesViewForm() {Register<SeriesViewForm, Series>();}
// ... details do not matter ...
}
// fails because CacheableViewForm.Register<> has not been executed yet!
CacheableViewForm newForm = CacheableViewForm.CreateFromTargetType(typeof(Series));
答案 0 :(得分:0)
我的解决方案是将初始化(从派生类的静态构造函数)移至基类的静态构造函数(在执行对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);}
// ...
}