Return to Snippet

Revision: 26635
at May 25, 2010 13:54 by bryanlyman


Updated Code
The problem: Lets say I want to construct a generic object, but all I have is a Type object
instance. The problem with the syntax of the IDE is that you must specify a keyword type
to a generic declaration not a Type object. For example:

public IList GetListFromType(Type memberType)
{
   return new MyList<memberType>();
}

This will not compile.
Also as of .net 4.0, generic indexers are not supported, therefore:

public T this<T>[int index]
{
   get 
   {
      object ret = MixedList[index];
      if (ret is T)
         return (T)ret;
      return null;
   }
}

...Will also not compile. This is somewhat annoying since we want to have a specific
Strongly Typed object returned from a collection of mixed object types only (easy filtering).

To allow this we turn to reflection. We still have generic casting restrictions, so we
cannot cast a Dictionary<B,A> to a Dictionary<A,A> even if class B is derived from 
class A. The only way to fix this is through interfaces. We must return an interface 
that is used by the derived classed, but we should be using interfaces for common public
functionality between derived classes anyway. So the solution is:

class A { }

class B : A { }

Interface IListAB
{
   int Count { get; }
}

class MyList<T> : List<T>, IListAB
{
   public MyList()
   {      
   }
}

IListAB NewListByType(Type elementType)
{
   Type classType = Type.GetType(this.GetType().Namespace) + ".MyList`1", false);
   Type genClassType = classType.MakeGenericType(elementType);
   ConstructorInfo ctor = genClassType.GetConstructors()[0]; //get single public constructor
   return (IListAB)ctor.Invoke(new object[] {});
}

From this method, you are returned a strongly-typed List as an interface reference. Notice
that we are looking up the class constructor by fully qualified name and the `1 after the
name of the generic class. The 1 indicates how many generic type arguments are used in the
class (a Dictionary<T1,T2> would have 2, and you would pass these types to the 
MakeGenericType() function). Using further reflection we can even see what type of generic
derivation the list is a type of, or we could simply put a method in the interface that 
returns this information based on the implementation of the class.

Revision: 26634
at May 25, 2010 13:53 by bryanlyman


Updated Code
The problem: Lets say I want to construct a generic object, but all I have is a Type object
instance. The problem with the syntax of the IDE is that you must specify a keyword type
to a generic declaration not a Type object. For example:

public IList GetListFromType(Type memberType)
{
   return new MyList<memberType>();
}

This will not compile.
Also as of .net 4.0, generic indexers are not supported, therefore:

public T this<T>[int index]
{
   get 
   {
      object ret = MixedList[index];
      if (ret is T)
         return (T)ret;
      return null;
   }
}

...Will also not compile. This is somewhat annoying since we want to have a specific
Strongly Typed object returned from a collection of mixed object types only (easy filtering).

To allow this we turn to reflection. We still have generic casting restrictions, so we
can't cast a Dictionary<B,A> to a Dictionary<A,A> even if class B is derived from 
class A. The only way to fix this is through interfaces. We must return an interface 
that is used by the derived classed, but we should be using interfaces for common public
functionality between derived classes anyway. So the solution is:

class A { }

class B : A { }

Interface IListAB
{
   int Count { get; }
}

class MyList<T> : List<T>, IListAB
{
   public MyList()
   {      
   }
}

IListAB NewListByType(Type elementType)
{
   Type classType = Type.GetType(this.GetType().Namespace) + ".MyList`1", false);
   Type genClassType = classType.MakeGenericType(elementType);
   ConstructorInfo ctor = genClassType.GetConstructors()[0]; //get single public constructor
   return (IListAB)ctor.Invoke(new object[] {});
}

From this method, you are returned a strongly-typed List as an interface reference. Notice
that we are looking up the class constructor by fully qualified name and the `1 after the
name of the generic class. The 1 indicates how many generic type arguments are used in the
class (a Dictionary<T1,T2> would have 2, and you would pass these types to the 
MakeGenericType() function). Using further reflection we can even see what type of generic
derivation the list is a type of, or we could simply put a method in the interface that 
returns this information based on the implementation of the class.

Revision: 26633
at May 25, 2010 13:51 by bryanlyman


Updated Code
The problem: Lets say I want to construct a generic object, but all I have is a Type object
instance. The problem with the syntax of the IDE is that you must specify a keyword type
to a generic declaration not a Type object. For example:

public IList GetListFromType(Type memberType)
{
   return new MyList<memberType>();
}

This will not compile.
Also as of .net 4.0, generic indexers are not supported, therefore:

public T this<T>[int index]
{
   get 
   {
      object ret = MixedList[index];
      if (ret is T)
         return (T)ret;
      return null;
   }
}

...Will also not compile. This is somewhat annoying since we want to have a specific StronglyTyped object returned from a collection of mixed object types only (easy filtering).

To allow this we turn to reflection. We still have generic casting restrictions, so we can't cast a Dictionary<B,A> to a Dictionary<A,A> even if class B is derived from class A. The only way to fix this is through interfaces. We must return an interface that is used by the derived classed, but we should be using interfaces for common public functionality between derived classes anyway. So the solution is:

class A { }

class B : A { }

Interface IListAB
{
   int Count { get; }
}

class MyList<T> : List<T>, IListAB
{
   public MyList()
   {      
   }
}

IListAB NewListByType(Type elementType)
{
   Type classType = Type.GetType(this.GetType().Namespace) + ".MyList`1", false);
   Type genClassType = classType.MakeGenericType(elementType);
   ConstructorInfo ctor = genClassType.GetConstructors()[0]; //get single public constructor
   return (IListAB)ctor.Invoke(new object[] {});
}

From this method, you are returned a strongly-typed List as an interface reference. Notice that we are looking up the class constructor by fully qualified name and the `1 after the name of the generic class. The 1 indicates how many generic type arguments are used in the class (a Dictionary<T1,T2> would have 2, and you would pass these types to the the MakeGenericType() function). Using further reflection we can even see what type of generic derivation the list is a type of, or we could simply put a method in the interface that returns this information based on the implementation of the class.

Revision: 26632
at May 4, 2010 16:58 by bryanlyman


Initial Code
The problem: Lets say I want to construct a generic object, but all I have is a Type object instance. The problem with the syntax of the IDE is that you must specify a keyword type to a generic declaration not a Type object. For example:

public IList GetListFromType(Type memberType)
{
   return new MyList<memberType>();
}

This will not compile.
Also as of .net 4.0, generic indexers are not supported, therefore:

public T this<T>[int index]
{
   get 
   {
      object ret = MixedList[index];
      if (ret is T)
         return (T)ret;
      return null;
   }
}

...Will also not compile. This is somewhat annoying since we want to have a specific StronglyTyped object returned from a collection of mixed object types only (easy filtering).

To allow this we turn to reflection. We still have generic casting restrictions, so we can't cast a Dictionary<B,A> to a Dictionary<A,A> even if class B is derived from class A. The only way to fix this is through interfaces. We must return an interface that is used by the derived classed, but we should be using interfaces for common public functionality between derived classes anyway. So the solution is:

class A { }

class B : A { }

Interface IListAB
{
   int Count { get; }
}

class MyList<T> : List<T>, IListAB
{
   public MyList()
   {      
   }
}

IListAB NewListByType(Type elementType)
{
   Type classType = Type.GetType(this.GetType().Namespace) + ".MyList`1", false);
   Type genClassType = classType.MakeGenericType(elementType);
   ConstructorInfo ctor = genClassType.GetConstructors()[0]; //get single public constructor
   return (IListAB)ctor.Invoke(new object[] {});
}

From this method, you are returned a strongly-typed List as an interface reference. Notice that we are looking up the class constructor by fully qualified name and the `1 after the name of the generic class. The 1 indicates how many generic type arguments are used in the class (a Dictionary<T1,T2> would have 2, and you would pass these types to the the MakeGenericType() function). Using further reflection we can even see what type of generic derivation the list is a type of, or we could simply put a method in the interface that returns this information based on the implementation of the class.

Initial URL


Initial Description
.net 2.0+ Generic classes make code size much smaller and casting objects (boxing) a cinch. However, currently there are some unsupported IDE options when trying to cast objects to and from generic objects that use mixed object types (inherited from a generic type specifier). Fear not, using reflection we can bypass the IDE and supply the users with strongly typed objects.

Initial Title
Constructing Generics Through Reflection (List of Mixed Types Example)

Initial Tags
class, list, c, Net

Initial Language
C#