2009-12-22 63 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});