例如,这里有一些代码来创建List int通过反射(是的,我知道有从数组转换到列表的函数,问题不是关于该解决方案,问题是关于使用反射而不事先知道类型. public static T ConvertT(int[] src){ Type
public static T Convert<T>(int[] src) { Type genericClassType = typeof(T); Type[] typeParameters = genericClassType.GetGenericArguments(); Type genericTypeDef = genericClassType.GetGenericTypeDefinition(); Type constructedClass = genericTypeDef.MakeGenericType(typeParameters); T arrayLike = (T)Activator.CreateInstance(constructedClass); System.Reflection.MethodInfo method = arrayLike.GetType().GetMethod("Add", typeParameters); foreach (int value in src) { method.Invoke(arrayLike, new []{(object)value}); } return arrayLike; }
所以我可以这样称呼它
int[] src = {4, 5, 6}; List<int> copy = Convert<List<int>>(src);
但我也希望能够这样称呼它
int[] src = {4, 5, 6}; Stack<int> copy = Convert<Stack<int>>(src); int[] src = {4, 5, 6}; Queue<int> copy = Convert<Queue<int>>(src);
但我不能因为例如Stack没有Add方法
实际上,我正在进行一些反序列化工作,并试图使其成为通用或半通用的.源数据没有类型信息.它只是一个int的数组,但是当调用反序列化代码时,我知道我希望它是List,Stack,Queue等类型…那么,是否可以一般转换为给定类型或者我必须继续编写每种通用的自定义代码?
我肯定在某种程度上List,Stack,Queue是不同的但是C/C++ / Assembly程序员在我看到给定一个int数组和所需的类型所有信息都在那里重建给定只有一个通用的构造函数(已经存在于上面的代码).
对于您的特定情况,如果您只是更改Convert方法以将src作为参数传递给构造函数,它将起作用:public static T Convert<T>(int[] src) { Type genericClassType = typeof(T); Type[] typeParameters = genericClassType.GetGenericArguments(); Type genericTypeDef = genericClassType.GetGenericTypeDefinition(); Type constructedClass = genericTypeDef.MakeGenericType(typeParameters); T arrayLike = (T)Activator.CreateInstance(constructedClass, src); return arrayLike; }
所以你可以像这样使用它:
int[] src = { 4, 5, 6 }; Stack<int> copy = Convert<Stack<int>>(src); Queue<int> copy2 = Convert<Queue<int>>(src); List<int> copy3 = Convert<List<int>>(src);
因此,您可能希望在构造函数中添加一些类型检查,以验证它是否可以接受IEnumerable< int>的类型.
但是你必须要知道顺序.例如,集合将按顺序包含:
复制:
6, 5, 4
copy2和copy3:
4, 5, 6
如果您希望副本以相同的顺序包含它们,只需反转数组:
Stack<int> copy = Convert<Stack<int>>(src.Reverse().ToArray());
Try it out