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

发布于 2024-12-09 15:57:55 字数 573 浏览 5 评论 0原文

我有一个与我的实体相对应的 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 实例化一个对象。我正在尝试做的事情有什么动态?

I have a list of Type objects corresponding to my entities, and I want to use those Types to instantiate corresponding generic binders...well let me just show this:

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);
.....................

The above works: each binder created is then later added to a dictionary of binders to be used by the mvc app. But why am I forced to use reflection? I believe this involves runtime vs compile time, which I don't understand. The types list is there at compile time.

If anyone can suggest a different pattern and/or explain these things to me then that would be nice. It seems like given a type object, I should be able to instantiate an object just using new. What is dynamic about what I am trying to do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

瞎闹 2024-12-16 15:57:55

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

foreach (Type entityType in Core.EntityList.Entities)
{   
    IModelBinder obj = new CustomBinders.Binder<entityType>()
    // Then add it to the dictionary
}

但是,这在 C# 中是非法的 - 它会给您错误“需要类型或命名空间名称”。泛型需要在编译时定义的类型参数,以便它可以提供所有编译时检查。因此,您需要使用反射来动态地执行此操作。

至于反射在这种情况下实际执行的操作:

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

这会获取对“未绑定”泛型类型的引用(即尚未为其提供类型参数)。

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

这为您提供了对“构造”类型的引用 - 即以实体类型作为类型参数的类型(即 CustomBinders.Binder)。

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

这将构造对象为你。

If you wanted to use new, you might think of doing something like this:

foreach (Type entityType in Core.EntityList.Entities)
{   
    IModelBinder obj = new CustomBinders.Binder<entityType>()
    // Then add it to the dictionary
}

However, this is illegal in C# - it will give you the error "Type or namespace name expected". Generics need a type parameter defined at compile-time so that it can provide all its compile-time checks. Thus, you need to use reflection to do this dynamically.

As for what reflection is actually doing in this case:

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

This gets a reference to the "unbound" generic type (i.e. it hasn't been given its type parameter yet).

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

This gives you a reference to the "constructed" type - that is, the one with entitytype as the type parameter (i.e. CustomBinders.Binder<entityType>)

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

This constructs the object for you.

错爱 2024-12-16 15:57:55

假设您想构建一个表。您已经预先知道尺寸、使用什么材料、成本是多少等等,因此您只需继续创建一个表格即可。

var table = new Table();

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

foreach(在 planBox 中输入计划)
Activator.CreateInstance(plan);

不同之处在于,Type 是您在运行时拥有的关于给定对象(可以说是计划)的一段元数据。如果您在编译时知道类型,则可以直接将其放入代码中,但您不知道 Core.EntityList.Entities 框中会发生什么,因此您必须使用反射适当地使用该运行时信息。

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

Say you want to build a table. You already know the dimensions up front, what material to use, how much it'll cost and so on, so you just go ahead and create a table.

var table = new Table();

Let's say you now want to expand that and build other people's tables for them as well, so you put a box out where people can put the plans for their custom tables. The box is there from the start, but you have no idea which plans are going to come through that box, and there could be an arbitrary number of them, so you'll have to work it on on the fly.

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

The difference is that a Type is a piece of metadata that you have at runtime about a given object (the plans, so to speak). If you knew the type at compile time, you'd put it into your code directly, but you have no idea what's going to come through your Core.EntityList.Entities box and so you have to use reflection to use that runtime information appropriately.

The point is, if you are using runtime information then you must use runtime capabilities. If all of the types are known at compile time, do not use Type objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文