铸造泛型类型的实例使用反射创建(Casting generic type instances cre

2019-06-25 20:08发布

我创建使用反射泛型类型的实例:

public interface IModelBuilder<TModel>
{
    TModel BuildModel();
}

public class MyModel
{
    public string Name { get; set; }
}

public class MyModelBuilder : IModelBuilder<MyModel>
{
    public MyModel BuildModel()
    {
        throw new NotImplementedException();
    }
}

在运行时,我们所知道的是如模型的类型MyModel 。 我能找到像这样的有关模型构建器的实例:

var modelBuilders = from t in Assembly.GetExecutingAssembly().GetTypes()
                from i in t.GetInterfaces()
                where i.IsGenericType
                        && i.GetGenericTypeDefinition() == typeof(IModelBuilder<>)
                        && i.GetGenericArguments()[0] == modelType
                select t;

var builder = Activator.CreateInstance(modelBuilders.First());

但我不知道我怎样才能再投的实例作为IModelBuilder<TModel> ,所以我可以打电话与结果工作BuildModel()

Answer 1:

由于modelType仅仅是一个Type的实例,你不能这样做自动,因为没有可用的非通用API。 各种选项:

1:使用反射,例如(未测试的)

object builder = Activator.CreateInstance(...);
var model=builder.GetType().GetMethod("BuildModel").Invoke(builder,null);

2:具有欺骗dynamic

dynamic builder = Activator.CreateInstance(...);
var model = builder.BuildModel();

3:使非通用版本IModelBuilder ,并使用该

需要注意的是1和2依赖于公共接口的实现 ,并将失败的(完全合法的)显式接口实现。 对于“1”,则可以通过解决这个问题:

var model = typeof(IModelBuilder<>).MakeGenericType(modelType)
       .GetMethod("BuildModel").Invoke(builder);

最后一个鬼鬼祟祟的选择是从非泛型方法翻转到一个通用的方法,所以泛型方法里面你可以直接使用的所有成员。 有一个偷懒的办法来做到这一点通过dynamic

interface ISneaky<T>
{
    T Foo { get; }
}
class Sneaky<T> : ISneaky<T>
{
    T ISneaky<T>.Foo { get { return default(T); } }
}
class Program
{
    static void Main()
    {
        Execute(typeof(int));
    }
    static void Execute(Type t)
    {
        dynamic obj = Activator.CreateInstance(
            typeof(Sneaky<>).MakeGenericType(t));
        // crafy hack to flip from non-generic code into generic code:
        Evil(obj);
    }
    static void Evil<T>(ISneaky<T> sneaky)
    {   // in here, life is simple; no more reflection
        Console.WriteLine("{0}: {1}", typeof(T).Name, sneaky.Foo);
    }
}


文章来源: Casting generic type instances created using Reflection
标签: c# reflection