2009-12-22 57 views
6

我有问题,在创建类型为List < MyClass01>的对象“oListType01”并将其分配给类型为“object”的另一个对象“oObjectType”之后,我无法访问任何更多函数“ElementAt(1)”。我尝试通过使用反射,但我总是在“调用”方法中得到异常(参数冲突)。有谁知道为什么? 米兰如何使用反射调用列表<T>的扩展方法“ElementAt”?

MyClass01 oMy1 = new MyClass01(); 
oMy1._ID = "1"; 

MyClass01 oMy2 = new MyClass01(); 
oMy2._ID = "3"; 

IList<MyClass01> oListType01 = new List<MyClass01>(); 

oListType01.Add(oMy1); 
oListType01.Add(oMy2); 

object oObjectType = new object(); 

oObjectType = oListType01; 

从这里fowrads唯一对象oObjectType可用(向上发生在单独的函数调用中的实际情况)。在VS oObjectType中显示了我希望每次反射访问的两个元素。

MethodInfo mInfo = typeof(System.Linq.Enumerable).GetMethod("ElementAt").MakeGenericMethod(typeof(object)); 
object oSingleObject = mInfo.Invoke(oObjectType, new object[] { 1 }); 
+0

为什么你首先将它分配给一个对象? 如果你必须出于某种原因,并且如果在编译时知道该列表总是包含MyClass01实例的类型,那么为什么不把它重新投入列表,如下所示: ((List )oObjectType).ElementAt(1); – tclem 2009-12-22 19:19:45

+0

plese看看“答案”,我解释说在invoke中可以只使用引用oObjectType(不是oListType01而不是MyClass01)。 – milan 2009-12-23 11:11:46

回答

9

我会假设你有一个合理的理由来做这件事,但看起来有点不对。这就是说这里有一些代码可以完成你正在尝试做的事情。

MethodInfo mInfo = typeof(System.Linq.Enumerable).GetMethod("ElementAt").MakeGenericMethod(typeof(MyClass01)); 
object oSingleObject = mInfo.Invoke(oObjectType, new object[] { oObjectType, 1 }); 

当我运行这段代码时,我得到列表中的第二个元素。

+0

请看看“答案”,我解释说在invoke中可以只引用oObjectType(不是oListType01)。 – milan 2009-12-23 11:11:00

+0

我改变了代码,所以它调用了引用。这应该做到这一点。 – 2009-12-23 15:00:19

+0

这对我有效,谢谢!只需要注意一点:mInfo.Invoke()的第一个参数可以为null。我们正在调用静态方法,而不是实例方法的方法。 – 2012-07-25 23:38:25

0

ElementAt扩展方法可能在IEnumerable <T>上,所以当你像对象一样对待你的列表时,扩展方法将不可用,除非你施放它。 ((列表<MyClass01>)oObjectType).ElementAt()或(oObjectType as List <MyClass01>).ElementAt()。

尽管如此,我还是要问,为什么你会想要这样做呢?这让我感到有些问题可以通过界面来完成。

+0

'IEnumerable'扩展方法在'System.Linq.Enumerable'类中。 – 2009-12-22 19:23:52

+0

来自System.Linq.Enumerable。 。 。 public static TSource ElementAt (this IEnumerable source,int index) {...} – 2009-12-22 19:38:58

+0

请看上面的答案,我解释了约束条件。 – milan 2009-12-23 11:12:31

0

如果我们可以安全地假设:

  • oObjectType是一些牛逼

一个IEnumerable的那么这里的代码,从中提取的项目。

注意,我认真地想知道这是去了解这个正确方式,但你有没有给我们足够的信息来帮助你找出是否有更好的办法,所以我们要留下的是只是回答问题。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using System.Diagnostics; 

namespace ConsoleApplication2 
{ 
    class MyClass01 
    { 
     public String _ID; 

     public override string ToString() 
     { 
      return _ID; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyClass01 oMy1 = new MyClass01(); 
      oMy1._ID = "1"; 

      MyClass01 oMy2 = new MyClass01(); 
      oMy2._ID = "3"; 

      IList<MyClass01> oListType01 = new List<MyClass01>(); 

      oListType01.Add(oMy1); 
      oListType01.Add(oMy2); 

      object oObjectType = new object(); 

      oObjectType = oListType01; 

      Test(oObjectType); 

      Console.In.ReadLine(); 
     } 

     private static void Test(object oObjectType) 
     { 
      Type tObject = oObjectType.GetType(); 
      Debug.Assert(tObject.IsGenericType); 
      Debug.Assert(tObject.GetGenericArguments().Length == 1); 
      Type t = tObject.GetGenericArguments()[0]; 

      Type tIEnumerable = typeof(IEnumerable<>).MakeGenericType(t); 
      Debug.Assert(tIEnumerable.IsAssignableFrom(tObject)); 

      MethodInfo mElementAt = 
       typeof(Enumerable) 
       .GetMethod("ElementAt") 
       .MakeGenericMethod(t); 

      Console.Out.WriteLine("o[0] = " + 
       mElementAt.Invoke(null, new Object[] { oObjectType, 0 })); 
      Console.Out.WriteLine("o[1] = " + 
       mElementAt.Invoke(null, new Object[] { oObjectType, 1 })); 
     } 
    } 
} 
0

这实在是类似于您other question,但在这种情况下,静态的ElementAt方法实际上是需要两个参数。试试这个:

object oSingleObject = mInfo.Invoke(null,new object [] {oObjectType,1});