从变量实例化泛型类型

本文关键字:泛型类型 实例化 变量 | 更新日期: 2023-09-27 18:11:41

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

var newListOfObjects = new List<TabViewModel>();

其中TabViewModel是以下对象:

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

当尝试仅使用变量实例化新对象时,问题就出现了。我们有一个泛型类型变量genericType,它是一个接口,还有一个类型参数列表listOfTypeArgs。在上面的例子中,泛型类型是IList,参数是TabViewModel。然后它看起来像这样(注意,为了更容易理解,有些代码是psudo):

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

很明显,我得到了错误'System '。MissingMethodException',并指出我无法从接口实例化变量。

我如何将接口转换为它的代表,以便我可以实例化新对象?

注:我不能改变类型genericType = IList'1;也不类型[]listOfTypeArgs = TabViewModel;

从变量实例化泛型类型

该错误是自描述的,您需要具体的类型来创建实例。而不是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));

您需要像这样使用List<>类型:

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