开发者

Why do I need to use reflection to instantiate a generic, given a type object?

I have a list of Typ开发者_如何学Pythone 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?


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜