为什么我需要使用反射来实例化给定类型对象的泛型?

本文关键字:类型 对象 泛型 实例化 反射 为什么 | 更新日期: 2023-09-27 18:11:05

我有一个与我的实体对应的Type对象列表,我想使用这些类型实例化相应的泛型绑定器…我来展示一下:

foreach (Type entitytype in Core.EntityList.Entities)
        {   
Type generictype = typeof(CustomBinders.Binder<>);
Type actualtype = generictype.MakeGenericType(new Type[] { entitytype });
IModelBinder custombinder = (IModelBinder)Activator.CreateInstance(actualtype);
.....................

上面的工作:创建的每个粘合剂随后被添加到粘合剂的字典中,以供mvc应用程序使用。但是为什么我被迫使用反射?我相信这涉及到运行时和编译时,我不理解。类型列表在编译时就存在了。

如果有人可以建议一个不同的模式和/或解释这些事情给我,那将是很好的。似乎给定一个类型对象,我应该能够使用new实例化一个对象。我想做的事情有什么动态的?

为什么我需要使用反射来实例化给定类型对象的泛型?

如果您想使用new,您可能会考虑这样做:

foreach (Type entityType in Core.EntityList.Entities)
{   
    IModelBinder obj = new CustomBinders.Binder<entityType>()
    // Then add it to the dictionary
}
然而,这在c#中是非法的——它会给你一个错误"Type or namespace name expected"。泛型需要在编译时定义类型参数,以便它可以提供所有编译时检查。因此,您需要使用反射来动态地执行此操作。

关于反射在这种情况下实际在做什么:

Type generictype = typeof(CustomBinders.Binder<>);

这将获得对"未绑定"泛型类型的引用(即尚未给出其类型参数)。

Type actualtype = generictype.MakeGenericType(new Type[] { entitytype });

这为您提供了对"构造的"类型的引用-即以entitytype作为类型参数的类型(即CustomBinders.Binder<entityType>)

IModelBinder custombinder = (IModelBinder)Activator.CreateInstance(actualtype);

为您构造对象

假设您想要构建一个表。您已经预先知道了尺寸,使用什么材料,花费多少等等,所以您只需继续创建一个表。

var table = new Table();

假设你现在想扩展它,并为他们建立其他人的表,所以你放了一个框,人们可以放他们的自定义表的计划。这个盒子从一开始就在那里,但是你不知道哪些计划将通过这个盒子,而且可能有任意数量的计划,所以你必须在飞行中处理它。

foreach(Type plan in planBox) Activator.CreateInstance(plan);

不同之处在于,Type是运行时关于给定对象(也就是计划)的一段元数据。如果你在编译时知道类型,你会把它直接放进你的代码中,但是你不知道Core.EntityList.Entities盒子里会有什么,所以你必须使用反射来适当地使用运行时信息。

关键是,如果您正在使用运行时信息,那么您必须使用运行时功能。如果所有类型在编译时都是已知的,则不要使用Type对象。