Generics and Reflection


In .NET 2.0, reflection is extended to support generic type parameters. The type Type can represent generic types with specific type parameters (called bounded types), or unspecified (unbounded) types. As in C# 1.1, you can obtain the Type of any type by using the typeof operator or by calling the GetType( ) method that every type supports. Regardless of the way you choose, both yield the same Type. For example, in the following code sample, type1 is identical to type2:

     LinkedList<int,string> list = new LinkedList<int,string>(  );     Type type1 = typeof(LinkedList<int,string>);     Type type2 = list.GetType(  );     Debug.Assert(type1 == type2);

Both typeof and GetType( ) can operate on naked generic type parameters:

     public class MyClass<T>     {        public void SomeMethod(T t)        {           Type type = typeof(T);           Debug.Assert(type == t.GetType(  ));        }     }

In addition, the typeof operator can operate on unbounded generic types (generic types that do not yet have specific type parameters). For example:

     public class MyClass<T>     {}     Type unboundedType = typeof(MyClass<>);     Trace.WriteLine(unboundedType.ToString(  ));     //Writes: MyClass`1[T]

The number 1 being traced is the number of generic type parameters of the type used. Note the use of the empty <>. To operate on an unbounded generic type with multiple type parameters, use a , in the empty <>:

     public class LinkedList<K,T>     {...}     Type unboundedList = typeof(LinkedList<,>);     Trace.WriteLine(unboundedList.ToString(  ));     //Writes: LinkedList`2[K,T]

To support generics, Type has special methods and properties designed to provide reflection information about the generic aspects of the types. Example C-5 shows these members.

Example C-5. Type's generic reflection members
 public abstract class Type : //Base types {    public virtual bool ContainsGenericParameters{get;}    public virtual Type[] GetGenericParameterConstraints(  );    public virtual GenericParameterAttributes GenericParameterAttributes{get;}    public virtual int GenericParameterPosition{get;}    public virtual bool IsGenericParameter{get;}    public virtual boolIsGenericType{get;}    public virtual bool IsGenericTypeDefinition{get;}    public virtual Type[] GetGenericArguments(  );    public virtual Type GetGenericTypeDefinition(  );    public virtual Type MakeGenericType(params Type[] typeArguments);    //Rest of the members }

The most useful of these new members are the IsGenericType property and the GetGenericArguments( ) and GetGenericTypeDefinition( ) methods. The rest of Type's generic-related members are for advanced and somewhat esoteric scenarios beyond the scope of this appendix. As its name indicates, IsGenericType is set to true if the type represented by the Type object uses generic type parameters. GetGenericArguments( ) returns an array of types corresponding to the bounded types used. GetGenericTypeDefinition( ) returns a Type representing the generic form of the underlying type.

Example C-6 demonstrates using these generic-handling Type members to obtain generic reflection information on a generic linked list.

Example C-6. Using Type for generic reflection
 public class LinkedList<K,T> {...} LinkedList<int,string> list = new LinkedList<int,string>(  ); Type boundedType = list.GetType(  ); Debug.Assert(boundedType.IsGenericType); Trace.WriteLine(boundedType.ToString(  )); //Writes: LinkedList`2[System.Int32,System.String] Type[] parameters = boundedType.GetGenericArguments(  ); Debug.Assert(parameters.Length == 2); Debug.Assert(parameters[0] == typeof(int)); Debug.Assert(parameters[1] == typeof(string)); Type unboundedType = boundedType.GetGenericTypeDefinition(  ); Debug.Assert(unboundedType.IsGenericTypeDefinition); Trace.WriteLine(unboundedType.ToString(  )); //Writes: LinkedList`2[K,T]

As shown in Example C-6, a Type can refer to a generic type with bounded parameters (boundedType in this example) or to a generic type with unbounded parameters (unboundedType in this example).

Like Type, MethodInfo and its base class MethodBase also have members that reflect generic method information.

As in the non-generic case, you can use MethodInfo (as well as a number of other options) for late-binding invocation. However, the type of the parameters you pass for the late binding must match the bounded types used, instead of the generic type parameters (if any):

     LinkedList<int,string> list = new LinkedList<int,string>(  );     Type type = list.GetType(  );     MethodInfo methodInfo = type.GetMethod("AddHead");     object[] args = {1,"AAA"};     methodInfo.Invoke(list,args);

Attributes and Generics

When defining an attribute, you can instruct the compiler that the attribute should target generic type parameters by using the GenericParameter value of the enum AttributeTargets:

     [AttributeUsage(AttributeTargets.GenericParameter)]     public class SomeAttribute : Attribute     {...}

Note that C# 2.0 does not allow you to define generic attributes:

     //Does not compile:     public class SomeAttribute<T> : Attribute     {...}

Yet internally, an attribute class can take advantage of generics by using generic types, or, like any other type, can define helper generic methods:

     public class SomeAttribute : Attribute     {        void SomeMethod<T>(T t)        {...}        LinkedList<int,string> m_List = new LinkedList<int,string>(  );     }



Programming. NET Components
Programming .NET Components, 2nd Edition
ISBN: 0596102070
EAN: 2147483647
Year: 2003
Pages: 145
Authors: Juval Lowy

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net