|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionHave you ever had to do something like this: string typeName = "MyDataType";
Type type = Type.GetType( typeName );
object o = someGenericClass<typeof(type)>();
If you have, then you have also discovered that this does not compile. The good news is this capability is possible in C#, but it's not obvious. This article is aimed at unmuddying the waters surrounding reflection and BackgroundWhy would you ever need to do something like this? I ran into this problem when creating an application framework that utilized dynamically loaded .NET Assemblies with well defined interfaces. Some of those interfaces were The problem occurred in implementing the framework, where the data types were not known at compile time, but were dynamically discovered through After much searching on the Internet and a lot of spelunking on MSDN, I finally discovered the secret sauce to using Generics with reflection. Types and GenericsThe key to all of this is in understanding the two different For all of our examples, we will be using the following namespace ReflectGenerics
{
public class GenericClass<T>
{
public GenericClass( T t )
{
_t = t;
Console.WriteLine( "GenericClass<{0}>( {1} ) created",
typeof( T ).FullName, _t.ToString() );
}
private T _t = default( T );
public T GetValue()
{
Console.WriteLine( "GetValue() invoked, returning {0}", _t.ToString() );
return _t;
}
public static U StaticGetValue<U>( U u )
{
Console.WriteLine( "StaticGetValue<{0}>( {1} ) invoked",
typeof( U ).FullName, u.ToString() );
return u;
}
}
}
Let's look at some code examples: // create an instance of a generic class
GenericClass<int> t = new GenericClass<int>( 1 );
// get the type of the generic class definition using just the class name
string typeName = "ReflectGenerics.GenericClass";
Type openGenericClass = Type.GetType( typeName );
// get the type of the generic class with the generic parameter defined
Type closedGenericClass = typeof( GenericClass<int> );
If we step through this code in a debugger and inspect the If we inspect To create an instance of an object from only its There is a helper method in the // get the type of the generic class from the class definition type
Type dynamicClosedGenericClass = openGenericClass.MakeGenericType( typeof( int ) );
Now that we've taken an open type and added the necessary generic type arguments to it, we can use this closed type to instantiate an object. object o = Activator.CreateInstance( dynamicClosedGenericClass, 1 );
object rv = dynamicClosedGenericClass.InvokeMember
( "GetValue", BindingFlags.InvokeMethod, null, o, new object[ 0 ] );
Console.WriteLine( "GetValue() returned {0}", rv.ToString() );
Note that this code is functionally equivalent to: GenericClass<int> t = new GenericClass<int>( 1 );
Console.WriteLine( "GetValue() returned {0}", t.GetValue() );
Generic MethodsThe only thing left for us to figure out are generic methods. Our sample // invoke the static template method directly
GenericClass<int>.StaticGetValue( 3 );
// get the open generic method type
MethodInfo openGenericMethod =
typeof( GenericClass<> ).GetMethod( "StaticGetValue" );
// get the close generic method type, by supplying the generic parameter type
MethodInfo closedGenericMethod =
openGenericMethod.MakeGenericMethod( typeof( int ) );
object o2 = closedGenericMethod.Invoke( null, new object[] { 4 } );
Console.WriteLine( "o2 = {0}", o2.ToString() );
SummarySo, we have learned how to take a History
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||