代码之家  ›  专栏  ›  技术社区  ›  Nick Larsen

反射实例化

  •  0
  • Nick Larsen  · 技术社区  · 14 年前

    我目前正在尝试创建一个通用实例工厂,它将一个接口作为通用参数(在构造函数中强制执行),然后让您获得实例化的对象,这些对象从所有加载的程序集中的所有类型实现该接口。

    目前的实施情况如下:

    public class InstantiationFactory<T>
    {
        protected Type Type { get; set; }
    
        public InstantiationFactory()
        {
            this.Type = typeof(T);
            if (!this.Type.IsInterface)
            {
                // is there a more descriptive exception to throw?
                throw new ArgumentException(/* Crafty message */);
            }
        }
    
        public IEnumerable<Type> GetLoadedTypes()
        {
            // this line of code found in other stack overflow questions
            var types = AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(a => a.GetTypes())
                .Where(/* lambda to identify instantiable types which implement this interface */);
    
            return types;
        }
    
        public IEnumerable<T> GetImplementations(IEnumerable<Type> types)
        {
            var implementations = types.Where(/* lambda to identify instantiable types which implement this interface */
                .Select(x => CreateInstance(x));
    
            return implementations;
        }
    
        public IEnumerable<T> GetLoadedImplementations()
        {
            var loadedTypes = GetLoadedTypes();
            var implementations = GetImplementations(loadedTypes);
            return implementations;
        }
    
        private T CreateInstance(Type type)
        {
            T instance = default(T);
    
            var constructor = type.GetConstructor(Type.EmptyTypes);
            if (/* valid to instantiate test */)
            {
                object constructed = constructor.Invoke(null);
                instance = (T)constructed;
            }
    
            return instance;
        }
    }
    

    我觉得把我的 CreateInstance(Type) 函数实现为扩展方法,以便稍后重用它并简化工厂的代码,但我不知道如何从该扩展方法返回强类型值。

    我意识到我可以返回一个对象:

    public static class TypeExtensions
    {
        public object CreateInstance(this Type type)
        {
            var constructor = type.GetConstructor(Type.EmptyTypes);
            return /* valid to instantiate test */ ? constructor.Invoke(null) : null;
        }
    }
    

    是否可以让扩展方法为其扩展的类型的每个实例创建签名?

    我的完美代码是这样的,这样就避免了将调用结果强制转换为 CreateInstance() :

    Type type = typeof(MyParameterlessConstructorImplementingType);
    MyParameterlessConstructorImplementingType usable = type.CreateInstance();
    
    3 回复  |  直到 9 年前
        1
  •  2
  •   Simon    14 年前

    我认为这是不可能的,因为你想 编译时间 键入您只知道的类型的信息(强类型) 运行时 . 你必须使用你的接口。

    问题是,您不知道在编译tim时哪些类型将包含在程序集中。甚至可以使用变量作为程序集的名称!程序集可以包含接口的任何实现。因此,不可能告诉编译器创建从程序集加载的类型的强类型实例。

        2
  •  0
  •   µBio    14 年前

    也许是这样?我不认为没有一个强制转换或一个泛型类型参数可以在内部处理强制转换。我使用类似的方法,其中我有一个子类类型的对象,但在调用者中只使用基类方法等。

    public static object New( this Type type )
    {
        return type.GetConstructor( Type.EmptyTypes ).Invoke( null );
    }
    
    public static T New<T>( this Type type )
    {
        return (T)type.GetConstructor( Type.EmptyTypes ).Invoke( null );
    }
    
    // usage
    MyParameterless usable = (MyParameterless)type.New();
    MyParameterless usable 2 = type.New<MyParameterless>();
    
        3
  •  0
  •   vGHazard    9 年前

    为什么不尝试在带有约束的扩展方法中使用泛型?

    public static class TypeExtensions
    {
        public T CreateInstance<T>(this T type) where T : Type
        {
            var constructor = type.GetConstructor(Type.EmptyTypes);
            return /* valid to instantiate test */ ? constructor.Invoke(null) : null;
        }
    }