Using a Type object to create a generic
I'm trying to create an instance of a generic class using a Type object.
Basically, I'll have a collection of objects of varying types at runtime, and since there's no way for sure to know what types they exactly will be, I'm thinking that I'll have to use Reflection.
I was working on something like:
Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
object obj = Activator.CreateInstance(genType);
Which is well and good. ^___^
The problem is, I'd like to access a method of my GenericType<> instance, which I can't because it's typed as an object class. I can't find a way to cast it obj into the specific GenericType<>, because that was the problem in the first place开发者_如何学JAVA (i.e., I just can't put in something like:)
((GenericType<elType>)obj).MyMethod();
How should one go about tackling this problem?
Many thanks! ^___^
You would have to continue using Reflection to invoke the actual method:
// Your code
Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
object obj = Activator.CreateInstance(genType);
// To execute the method
MethodInfo method = genType.GetMethod("MyMethod",
BindingFlags.Instance | BindingFlags.Public);
method.Invoke(obj, null);
For more information see Type.GetMethod and MethodBase.Invoke.
Once you start the reflection game you have to play it till the end. The type is not known at compile time, so you cannot cast it. You'll have to invoke the method by reflection:
obj.GetType().InvokeMember(
"MyMethod",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
null,
obj,
null
);
In C# 3.5 you have to use Type.GetMethod
and MethodInfo.Invoke
to call the method.
In C# 4 you can use the dynamic
keyword and bind to the method at runtime.
The most straightforward approach is to extract a non-generic supertype (either base class or interface) from GenericType that contains the methods you want to expose for this purpose:
class GenericType<T> : GenericBase { ... }
class GenericBase { abstract void MyMethod(); }
Failing that, use reflection to access the method itself as suggested by @Aaronaught.
Once you've created the instance, just do:
MethodInfo method = genType.GetMethod("MyMethod");
method.Invoke(obj, null);
If you know the signature of the methods you want to invoke, you can not only use MethodInfo.Invoke()
as shown in other samples here but also create a delegate which allows for more efficient invocation (if you need to invoke the same method several times) using Delegate.CreateDelegate()
.
I'm not sure how much your types vary or if you have control over the methods that you'll be calling in them, but it might be useful to create an interface that defines which set of functions you're going to be calling. So after creating the instance, you can cast to the interface and call whatever functions you need.
so create your standard interface (which you'll need to implement in each type, if you have control over them):
interface IMyInterface
{
void A();
int B();
}
class One : IMyInterface
{
...
implement A and B
...
}
Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
IMyInterface obj = (IMyInterface)Activator.CreateInstance(genType);
obj.A();
精彩评论