c#可插拔工厂/静态初始化

c#可插拔工厂/静态初始化,c#,static,C#,Static,我正在为一个可插拔工厂寻找与我的代码c#等价的代码。链接方法的优点是静态初始化会导致推送操作,每个插件都会将自己添加到工厂中 可插入工厂的C++代码:() //插件的基类 福班{ 公众: 虚拟std::string getName()const=0; 虚空练习()常量=0; }; //插件工厂 食品级工厂{ 公众: 静态Foo*GetA(std::string s); typedef std::map mapType; 静态映射类型&getA(); }; FooFactory::mapType&

我正在为一个可插拔工厂寻找与我的代码c#等价的代码。链接方法的优点是静态初始化会导致推送操作,每个插件都会将自己添加到工厂中

可插入工厂的C++代码:()

//插件的基类
福班{
公众:
虚拟std::string getName()const=0;
虚空练习()常量=0;
};
//插件工厂
食品级工厂{
公众:
静态Foo*GetA(std::string s);
typedef std::map mapType;
静态映射类型&getA();
};
FooFactory::mapType&FooFactory::getA(){static mapType getA;return getA;}
Foo*FooFactory::GetA(std::string s)
{return getA().find(s)!=getA().end()?getA()[s]():0;}//以简化访问
//帮助函数添加乐趣
模板
Foo*getNew(){返回新的T;}
//使用CRTP自动向工厂注册对象。

模板结构Reg{Reg(){/*cout我不太担心反射。即使是PEX使用它也没有问题。简单地说,通过反射,您只需检查程序集的元数据,看看它是否定义了实现某个接口的类或用某个属性标记的类,这非常快!无论如何,CLR永远不会运行未被ca验证的代码因此,不,您必须求助于某种拉动机制(即使您使其看起来像一个推动机制)

意识到这里唯一真正的要求是在一天结束时,我们在类型标识符(字符串/类型)之间进行查找一个函数允许我们获取该类型的实例,我最终通过以下模式解决了这个问题:

    private static readonly Dictionary<string, KeyValuePair<TConstructor, Node>> Types =
        new Dictionary<string, KeyValuePair<TConstructor, Node>>();
    private static readonly Dictionary<Type, string> classNameMap = new Dictionary<Type, string>();

    private class constructableNode<T> where T : Node, new()
    {
        public constructableNode()
        {
            var t = new T();
            Types[t.Type()] = new KeyValuePair<TConstructor, Node>(thisTConstructor, t);
            classNameMap[typeof (T)] = t.Type();
        }

        private static T thisTConstructor()
        {
            var t = new T();
            return t;
        }
    }

    public static Node GetA(string s)
    {
        if (Types.ContainsKey(s) == false)
        {
            UpdateAvailableTypes();
        }
        if (Types.ContainsKey(s) == false)
        {
            throw new BadNodeType(s);
        }
        // look up the correct constructor, and call it.
        return Types[s].Key();
    }

    public static void UpdateAvailableTypes()
    {
        Assembly targetAssembly = Assembly.GetExecutingAssembly(); // or whichever - could iterate dlls in the plugins folder or something
        UpdateAvailableTypes(targetAssembly);
        classNameMap[typeof (Node)] = "BaseNode"; // HARD CODED INTO the node type itself also
    }

    private static void UpdateAvailableTypes(Assembly targetAssembly)
    {
        IEnumerable<Type> subtypes = targetAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof (Node)));
        Type nodeConstructor = typeof (constructableNode<>);
        foreach (Type currentType in subtypes)
        {
            // this line throwing an error means that the Node type does not have an empty constructor.
            Activator.CreateInstance(nodeConstructor.MakeGenericType(currentType));

        }
    }
私有静态只读字典类型=
新字典();
私有静态只读字典classNameMap=新字典();
私有类constructableNode,其中T:Node,new()
{
公共可构造节点()
{
var t=新的t();
Types[t.Type()]=新的键值对(thisTConstructor,t);
classNameMap[typeof(T)]=T.Type();
}
私有静态T thisTConstructor()
{
var t=新的t();
返回t;
}
}
公共静态节点GetA(字符串s)
{
if(Types.ContainsKey)==false)
{
UpdateAvailableTypes();
}
if(Types.ContainsKey)==false)
{
抛出新的坏节点类型;
}
//查找正确的构造函数,并调用它。
返回类型[s].Key();
}
公共静态void UpdateAvailableTypes()
{
Assembly targetAssembly=Assembly.getExecutionGassembly();//或其他-可以迭代插件文件夹中的DLL或其他内容
更新可用类型(targetAssembly);
classNameMap[typeof(Node)]=“BaseNode”;//也硬编码到节点类型本身中
}
私有静态void UpdateAvailableTypes(程序集目标Assembly)
{
IEnumerable subtype=targetAssembly.GetTypes()。其中(t=>t.IsSubclassOf(typeof(Node));
类型nodeConstructor=typeof(可构造节点);
foreach(子类型中的类型currentType)
{
//此行抛出错误意味着节点类型没有空构造函数。
Activator.CreateInstance(nodeConstructor.MakeGenericType(currentType));
}
}
这是一个简单的方法,但与其他选项相比,每次调用动态调用的成本有点高,当我第一次在下面的部分中使用此模式时,它是关键代码路径运行时的80%

然而:由于性能限制,我的部分代码需要一种不同的构造模式,这部分代码重建得很快(可能有数百万个对象,需要次秒的响应时间)。(有关基于反射的构造的各种方法,请参阅的讨论)

对于这些,我需要以下构造范例,即通过对泛型类的函数调用进行的中间查找被清除

static buildCostItems()
        {
            //from http://blogs.msdn.com/b/haibo_luo/archive/2005/11/17/494009.aspx
            AssemblyBuilder asmBldr = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("inmemory"),
                                                                                    AssemblyBuilderAccess.Run);
            ModuleBuilder modBldr = asmBldr.DefineDynamicModule("helper");
            TypeBuilder typeBldr = modBldr.DefineType("ClassFactory");
            Type tci = typeof (CostsItem);
            IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes().Where(tci.IsAssignableFrom);
 //// Note -- assumption of currently executing assembly -- this isn't a requirement, but didn't need the dynamic callback capabilities of the Node constructor here.
            List<Type> enumerable = types as List<Type> ?? types.ToList();
            foreach (Type type in enumerable)
            {
                MethodBuilder methBldr = typeBldr.DefineMethod(type.Name,
                                                               MethodAttributes.Public | MethodAttributes.Static, type,
                                                               new[] {typeof (CostsItem)});
                ILGenerator ilgen = methBldr.GetILGenerator();
                ilgen.Emit(OpCodes.Nop);
                ilgen.Emit(OpCodes.Ldarg_0);
                ilgen.Emit(OpCodes.Newobj, type.GetConstructor(new[] {typeof (CostsItem)}));
                ilgen.Emit(OpCodes.Ret);
            }
            Type baked = typeBldr.CreateType();
            foreach (Type type in enumerable)
                ctors.Add(type,
                          (CtorCloneDelegate)
                          Delegate.CreateDelegate(typeof (CtorCloneDelegate), baked.GetMethod(type.Name)));
        }
static buildCostItems()
{
//从http://blogs.msdn.com/b/haibo_luo/archive/2005/11/17/494009.aspx
AssemblyBuilder asmBldr=AppDomain.CurrentDomain.DefinedDynamicAssembly(新的程序集名称(“inmemory”),
AssemblyBuilderAccess.Run);
ModuleBuilder modBldr=asmBldr.definedDynamicModule(“助手”);
TypeBuilder typeBldr=modBldr.DefineType(“类工厂”);
类型tci=类型(CostsItem);
IEnumerable types=Assembly.getExecutionGassembly().GetTypes().Where(tci.IsAssignableFrom);
////注意——假设当前正在执行程序集——这不是一个要求,但这里不需要节点构造函数的动态回调功能。
List enumerable=类型为List??types.ToList();
foreach(可枚举中的类型)
{
MethodBuilder methBldr=typeBldr.DefineMethod(type.Name,
MethodAttributes.Public | MethodAttributes.Static,类型,
新[]{typeof(CostsItem)});
ILGenerator ilgen=methBldr.GetILGenerator();
ilgen.Emit(操作码Nop);
ilgen.Emit(操作码Ldarg_0);
Emit(OpCodes.Newobj,type.GetConstructor(new[]{typeof(CostsItem)}));
ilgen.Emit(操作码Ret);
}
Type baked=typeBldr.CreateType();
foreach(可枚举中的类型)
添加(类型,
(clonedelegate)
CreateDelegate(typeof(CtorCloneDelegate),bake.GetMethod(type.Name));
}

作为旁白,我应该在这里还是那里包含代码板代码?一般来说,是的,在questi中包含代码片段并没有坏处
static buildCostItems()
        {
            //from http://blogs.msdn.com/b/haibo_luo/archive/2005/11/17/494009.aspx
            AssemblyBuilder asmBldr = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("inmemory"),
                                                                                    AssemblyBuilderAccess.Run);
            ModuleBuilder modBldr = asmBldr.DefineDynamicModule("helper");
            TypeBuilder typeBldr = modBldr.DefineType("ClassFactory");
            Type tci = typeof (CostsItem);
            IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes().Where(tci.IsAssignableFrom);
 //// Note -- assumption of currently executing assembly -- this isn't a requirement, but didn't need the dynamic callback capabilities of the Node constructor here.
            List<Type> enumerable = types as List<Type> ?? types.ToList();
            foreach (Type type in enumerable)
            {
                MethodBuilder methBldr = typeBldr.DefineMethod(type.Name,
                                                               MethodAttributes.Public | MethodAttributes.Static, type,
                                                               new[] {typeof (CostsItem)});
                ILGenerator ilgen = methBldr.GetILGenerator();
                ilgen.Emit(OpCodes.Nop);
                ilgen.Emit(OpCodes.Ldarg_0);
                ilgen.Emit(OpCodes.Newobj, type.GetConstructor(new[] {typeof (CostsItem)}));
                ilgen.Emit(OpCodes.Ret);
            }
            Type baked = typeBldr.CreateType();
            foreach (Type type in enumerable)
                ctors.Add(type,
                          (CtorCloneDelegate)
                          Delegate.CreateDelegate(typeof (CtorCloneDelegate), baked.GetMethod(type.Name)));
        }