通过反射构造泛型(混合类型列表示例)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过反射构造泛型(混合类型列表示例)相关的知识,希望对你有一定的参考价值。

.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.
  1. The problem: Lets say I want to construct a generic object, but all I have is a Type object
  2. instance. The problem with the syntax of the IDE is that you must specify a keyword type
  3. to a generic declaration not a Type object. For example:
  4.  
  5. public IList GetListFromType(Type memberType)
  6. {
  7. return new MyList<memberType>();
  8. }
  9.  
  10. This will not compile.
  11. Also as of .net 4.0, generic indexers are not supported, therefore:
  12.  
  13. public T this<T>[int index]
  14. {
  15. get
  16. {
  17. object ret = MixedList[index];
  18. if (ret is T)
  19. return (T)ret;
  20. return null;
  21. }
  22. }
  23.  
  24. ...Will also not compile. This is somewhat annoying since we want to have a specific
  25. Strongly Typed object returned from a collection of mixed object types only (easy filtering).
  26.  
  27. To allow this we turn to reflection. We still have generic casting restrictions, so we
  28. cannot cast a Dictionary<B,A> to a Dictionary<A,A> even if class B is derived from
  29. class A. The only way to fix this is through interfaces. We must return an interface
  30. that is used by the derived classed, but we should be using interfaces for common public
  31. functionality between derived classes anyway. So the solution is:
  32.  
  33. class A { }
  34.  
  35. class B : A { }
  36.  
  37. Interface IListAB
  38. {
  39. int Count { get; }
  40. }
  41.  
  42. class MyList<T> : List<T>, IListAB
  43. {
  44. public MyList()
  45. {
  46. }
  47. }
  48.  
  49. IListAB NewListByType(Type elementType)
  50. {
  51. Type classType = Type.GetType(this.GetType().Namespace) + ".MyList`1", false);
  52. Type genClassType = classType.MakeGenericType(elementType);
  53. ConstructorInfo ctor = genClassType.GetConstructors()[0]; //get single public constructor
  54. return (IListAB)ctor.Invoke(new object[] {});
  55. }
  56.  
  57. From this method, you are returned a strongly-typed List as an interface reference. Notice
  58. that we are looking up the class constructor by fully qualified name and the `1 after the
  59. name of the generic class. The 1 indicates how many generic type arguments are used in the
  60. class (a Dictionary<T1,T2> would have 2, and you would pass these types to the
  61. MakeGenericType() function). Using further reflection we can even see what type of generic
  62. derivation the list is a type of, or we could simply put a method in the interface that
  63. returns this information based on the implementation of the class.

以上是关于通过反射构造泛型(混合类型列表示例)的主要内容,如果未能解决你的问题,请参考以下文章

javajav 通过 反射 获取 泛型信息

是否有通用方法通过C#中的反射填充各种泛型集合?

如何反射获取List<T> 中泛型的类型

java 27 - 7 反射之 通过反射越过泛型检查

泛型反射常见应用,通过类型创建实例,通过反射实现增删改查

Java通过反射获取泛型类型信息