繁体   English   中英

在C#中使用Reflection进行转换

[英]Cast using Reflection in C#

我已经创建了一个通用函数(仅作为证明),它将采用List<T>集合并将其反转,返回一个新的List<T>作为其输出。

public static List<T> ReverseList<T>(List<T> sourceList)
{
    T[] outputArray = new T[sourceList.Count];
    sourceList.CopyTo(outputArray);
    return outputArray.Reverse().ToList();
}

证明的目的是我只知道T在运行时是什么。 因此我使用反射来调用上面的方法如下:

List<int> myList = new List<int>() { 1, 2, 3, 4, 5 }; // As an example, but could be any type for T

MethodInfo myMethod = this.GetType().GetMethod("ReverseList");
MethodInfo resultMethod = myMethod.MakeGenericMethod(new Type[] { typeof(int) });
object result = resultMethod.Invoke(null, new object[] { myList });

这里有两个问题:

  1. 在第二行,而不是提供typeof(int) ,我想提供类似于myList.GetType().GetGenericArguments()[0].GetType()东西,以便使事情更灵活,因为我不知道T直到运行。 当Invoke运行时,执行此操作会导致运行时错误,如下所示:“System.Collections.Generic.List'1 [System.Int32]类型的对象'无法转换为类型'System.Collections.Generic.List'1 [ System.RuntimeType]”。”
  2. Invoke()方法的结果返回一个对象。 在调试时,我可以看到该对象是List类型,但是尝试使用它告诉我,我有一个无效的强制转换。 我假设我需要使用反射将结果打包成正确的类型(即在此示例中,等效于(result as List<int> )。

有没有人有任何可以帮我解决这个问题的指针? 如果不清楚,我可能会道歉,如果被问到,我可能会提供更多细节。

TIA

你有一个GetType()太多了。 发生在所有人身上。

myList.GetType().GetGenericArguments()[0]是一个System.Type - 你正在寻找的那个。

myList.GetType().GetGenericArguments()[0].GetType()是一个System.Type描述System.Type (实际上具体子类System.RuntimeType )。


此外,您的ReverseList功能严重过度杀伤。 它只是为了避免调用List.Reverse执行额外的复制。 有一种更好的方法来规避:

public static List<T> ReverseList<T>(List<T> sourceList)
{
    return Enumerable.Reverse(sourceList).ToList();
}

要么

public static List<T> ReverseList<T>(List<T> sourceList)
{
    var result = new List<T>(sourceList);
    result.Reverse();
    return result;
}

要么

public static List<T> ReverseList<T>(List<T> sourceList)
{
    var result = new List<T>();
    result.Capacity = sourceList.Count;
    int i = sourceList.Count;
    while (i > 0)
        result.Add(sourceList[--i]);
    return result;
}

要以List<T>访问它,是的,您需要使用反射找到T(可能在接口上,例如typeof(IList<>) ,并使用更多反射和MakeGenericMethod等。说实话,它不是'值得的是:你会更好地检查非通用的IList

var list = result as IList;
if (list != null)
{
    // loop over list etc
}

泛型广告反映不是好朋友。

请注意,在4.0中,您还可以使用dynamic和泛型来完成一些技巧。

Invoke()方法的结果返回一个对象。 在调试时,我可以看到该对象是List类型,但是尝试使用它告诉我,我有一个无效的强制转换。 我假设我需要使用反射将结果打包成正确的类型(即在此示例中,等效于(结果为List)。

唯一的解决方法是我能想到的是传递一个空列表作为方法的第二个参数并填充该列表 - Invoke()返回的Invoke()始终只是类型对象,但在泛型方法中你有权访问类型本身:

List<int> reverseList = new List<int>();
resultMethod.Invoke(null, new object[] { myList, reverseList });

...

public static void ReverseList<T>(List<T> sourceList, List<T> resultList)
{
    T[] outputArray = new T[sourceList.Count];
    sourceList.CopyTo(outputArray);
    resultList.AddRange(outputArray.Reverse());
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM