簡體   English   中英

轉換使用Reflection創建的泛型類型實例

[英]Casting generic type instances created using Reflection

我正在使用反射創建泛型類型的實例:

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()的結果。

由於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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM