简体   繁体   English

静态构造函数注册对象构造函数=>未调用

[英]Static constructor registers object constructor => not called

I wanted to use a static constructor in derived classes to register object constructor lambdas for those classes to be called when passing a certain Type object. 我想在派生类中使用静态构造函数来为传递某个Type对象时要调用的那些类注册对象构造函数lambdas。

Since a static constructor is only called just before the first object of that class is created BUT I want to use the result of the static constructor to determine what kind of object to create, this mechanism fails, the constructor lambda is not found. 由于仅在创建该类的第一个对象之前才调用静态构造函数,但是我想使用静态构造函数的结果来确定要创建哪种对象,因此该机制失败,未找到构造函数lambda。

Is there any way out of this? 这有什么办法吗?

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));

My solution is to move initialization (from the static constructor of the derived classes) to the static constructor of the base class (which gets called automatically before executing my first call to the CreateFromTargetType method) and using reflection in there to examine the derived classes. 我的解决方案是将初始化(从派生类的静态构造函数)移动到基类的静态构造函数(在执行我对CreateFromTargetType方法的第一次调用之前自动调用)并在其中使用反射来检查派生类。 In the derived classes I defined static methods ( TargetType ) which return the specific Type they are operating on. 在派生类中,我定义了静态方法( TargetType ),它返回它们正在操作的特定Type

Neither elegant nor compact, and certainly not super fast, but it allows me to keep the association between derived class (eg SeriesViewForm ) and the data type it operates on ( typeof(Series) ) close together (in the same class definition). 既不优雅也不紧凑,当然也不是超快,但它允许我保持派生类(例如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);}

    // ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM