【问题标题】:Instantiate generic type from variable从变量实例化泛型类型
【发布时间】:2016-10-06 07:36:50
【问题描述】:

我想实例化一个新对象,其中类型和泛型类型被定义为变量。最终结果可能类似于此处手动创建的 newListOfObjects:

var newListOfObjects = new List<TabViewModel>();

其中 TabViewModel 是以下对象:

public class TabViewModel
{
    public string Title { get; set; }
    public int TabOrder { get; set; }
}

问题出现在尝试仅使用变量实例化新对象时。我们有一个泛型类型变量 genericType,它是一个接口和一个类型参数列表 listOfTypeArgs。在上面的示例中,泛型类型是 IList,参数是 TabViewModel。然后看起来如下(注意,为了便于理解,有些代码是伪代码):

Type genericType = IList'1;
Type[] listOfTypeArgs = TabViewModel;
var newObject = Activator.CreateInstance(genericType.MakeGenericType(listOfTypeArgs));

很明显,我收到错误“System.MissingMethodException”,并指出我无法从接口实例化变量。

如何将界面转换为其代表,以便我可以 实例化新对象?

注意:我无法更改 Type genericType = IList'1;也不 Type[] listOfTypeArgs = TabViewModel;

【问题讨论】:

  • 这个Type genericType = IList'1; 和这个Type[] listOfTypeArgs = TabViewModel; 不是有效的C# 语法。贴出实际代码!
  • 在这种情况下,获取 IList 和 TabViewModel 类型的有效代码无关紧要。
  • 如果您选择忽略 user3185569 的请求,您可能会在再次发布之前阅读stackoverflow.com/help/mcve

标签: c# variables object generics instantiation


【解决方案1】:

错误是自我描述的,您需要具体类型来创建实例。而不是IList(没有实现,只是一个合同),你需要使用IList的实现:

Type genericType = typeof(List<>);
Type[] listOfTypeArgs = new[] { typeof(TabViewModel) };
var newObject = Activator.CreateInstance(genericType.MakeGenericType(listOfTypeArgs));

编辑:

如果您没有具体类型,则需要使用容器或反映当前程序集来获取它。下面是一些小技巧,您需要调整您认为对您的案例有用的方式。

Type genericType = typeof(List<>);
Type concreteType = AppDomain.CurrentDomain.GetAssemblies()
                            .SelectMany(s => s.GetTypes())
                            .Where(p => genericType.IsAssignableFrom(p)).FirstOrDefault();

Type[] listOfTypeArgs = new[] { typeof(TabViewModel) };
var newObject = Activator.CreateInstance(concreteType.MakeGenericType(listOfTypeArgs));

【讨论】:

  • 可爱的回答,但遗憾的是我无法更改 genericType 变量。我得到的只是界面,这就是我的问题
  • @ViktorLeandersson 然后您需要使用反射来找到该接口的实现。检查编辑的答案
【解决方案2】:

您需要像这样使用List&lt;&gt; 类型:

var genericType = typeof(List<>);
var boundType = genericType.MakeGenericType(typeof(TabViewModel));
var instance = Activator.CreateInstance(boundType);

【讨论】:

  • 可爱的回答,但遗憾的是我无法更改 genericType 变量。我得到的只是界面,这就是我的问题
  • @ViktorLeandersson 然后您可以创建一个映射,将所有可能的接口映射到具体实现,例如IList&lt;&gt; 映射到 List&lt;&gt;
猜你喜欢
  • 1970-01-01
  • 2013-10-03
  • 2011-04-02
  • 1970-01-01
  • 1970-01-01
  • 2013-09-18
  • 1970-01-01
相关资源
最近更新 更多