C# 反射实例化

C# 反射实例化,c#,.net,reflection,extension-methods,instantiation,C#,.net,Reflection,Extension Methods,Instantiation,我目前正在尝试创建一个通用实例工厂,它将接口作为通用参数(在构造函数中强制),然后让您从所有加载的程序集中的所有类型中获取实现该接口的实例化对象 目前的实施情况如下: public class InstantiationFactory<T> { protected Type Type { get; set; } public InstantiationFactory() { this.Type = typeof(T); if

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

目前的实施情况如下:

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()
的结果:


我认为这是不可能的,因为您正试图获取只有在运行时才知道的类型的编译时类型信息(强类型)。 您必须使用您的接口


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

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

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>();
公共静态对象新建(此类型)
{
返回类型.GetConstructor(type.EmptyTypes).Invoke(null);
}
公共静态T新建(此类型)
{
return(T)type.GetConstructor(type.EmptyTypes).Invoke(null);
}
//用法
MyParameterless可用=(MyParameterless)type.New();
MyParameterless可用2=type.New();

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

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;
    }
}
公共静态类类型扩展
{
公共T CreateInstance(此T类型),其中T:type
{
var constructor=type.GetConstructor(type.EmptyTypes);
return/*对实例化test*/?构造函数有效。Invoke(null):null;
}
}

很抱歉,文本被弄乱了。。。在我的手机上发布你的方法的问题是你知道类型(你甚至写下:“MyParemeterless”)。当他从一个组件加载它时,他不知道。正确。在我自己使用simlilar的代码中,我不知道实际的运行时类型,但我知道基类型。这些也是从程序集(我没有编写)加载的。参见他给出的示例用法“Type Type=typeof(MyParameterlessConstructorImplementingType);MyParameterlessConstructorImplementingType可用=type.CreateInstance();'还有我帖子中的限定句“我看不到没有……”
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>();
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;
    }
}