Home
Manage Your Code
Snippet: Constructing Generics Through Reflection (List of Mixed Types Example) (C#)
Title: Constructing Generics Through Reflection (List of Mixed Types Example) Language: C#
Description: Using reflection we can bypass the IDE and supply the users with strongly typed generic objects. Views: 460
Author: Bryan Lyman Date Added: 10/14/2011
Copy Code  
1/*
2The problem: Lets say I want to construct a generic object, but all I have is a Type object
3instance. The problem with the syntax of the IDE is that you must specify a keyword type
4to a generic declaration not a Type object. For example:
5*/
6 
7public IList GetListFromType(Type memberType)
8{
9   return new MyList<memberType>();
10}
11 
12/*
13This will not compile.
14Also as of .net 4.0, generic indexers are not supported, therefore:
15*/
16 
17public T this<T>[int index]
18{
19   get 
20   {
21      object ret = MixedList[index];
22      if (ret is T)
23         return (T)ret;
24      return null;
25   }
26}
27
28/* 
29...Will also not compile. This is somewhat annoying since we want to have a specific
30Strongly Typed object returned from a collection of mixed object types only (easy filtering).
31 
32To allow this we turn to reflection. We still have generic casting restrictions, so we
33cannot cast a Dictionary<B,A> to a Dictionary<A,A> even if class B is derived from 
34class A. The only way to fix this is through interfaces. We must return an interface 
35that is used by the derived classed, but we should be using interfaces for common public
36functionality between derived classes anyway. So the solution is:
37*/
38 
39class A { }
40 
41class B : A { }
42 
43Interface IListAB
44{
45   int Count { get; }
46}
47 
48class MyList<T> : List<T>, IListAB
49{
50   public MyList()
51   {      
52   }
53}
54 
55IListAB NewListByType(Type elementType)
56{
57   Type classType = Type.GetType(this.GetType().Namespace) + ".MyList`1", false);
58   Type genClassType = classType.MakeGenericType(elementType);
59   ConstructorInfo ctor = genClassType.GetConstructors()[0]; //get single public constructor

60   return (IListAB)ctor.Invoke(new object[] {});
61}
62 
63/*
64From this method, you are returned a strongly-typed List as an interface reference. Notice
65that we are looking up the class constructor by fully qualified name and the `1 after the
66name of the generic class. The 1 indicates how many generic type arguments are used in the
67class (a Dictionary<T1,T2> would have 2, and you would pass these types to the 
68MakeGenericType() function). Using further reflection we can even see what type of generic
69derivation the list is a type of, or we could simply put a method in the interface that 
70returns this information based on the implementation of the class.
71*/
Usage
IListAB strongList = NewListByType(myObject.GetType())
Notes
Two un-compilable examples and the solution