2009-12-22 7 views
6

Ich habe das Problem, dass nach dem Erstellen des Objekts "oListType01" vom Typ List < MyClass01> und nach dem Zuweisen zu dem anderen Objekt "oObjectType" vom Typ "Objekt" kann ich keine weitere Funktion "ElementAt (1)" zugreifen. Ich habe versucht, mit Reflektion, aber ich bekomme immer Ausnahme (Parameterkonflikt) in "Invoke" -Methode. Weiß jemand warum? MilanSo rufen Sie die Erweiterungsmethode "ElementAt" der Liste <T> mit Reflektion auf?

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; 

Von hier fowrads nur Objekt oObjectType verfügbar ist (geschieht nach oben in separaten Funktionsaufruf in der realen Fall). In VS oObjectType zeigt zwei Elemente an, auf die ich pro Reflexion zugreifen möchte.

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

Warum ordnen Sie es einem Objekt überhaupt zu? Wenn Sie aus irgendeinem Grund, und wenn Sie zur Kompilierzeit wissen, welcher Typ, die Liste immer MyClass01-Instanzen enthalten wird, warum werfen Sie es nicht einfach zurück auf eine Liste ((Liste ) oObjectType) .ElementAt (1); – tclem

+0

Bitte schauen Sie sich "answer" an, wo ich erklärt habe, dass in invoke nur der Verweis auf den oObjectType verwendet werden kann (nicht oListType01 und nicht MyClass01). – milan

Antwort

9

Ich nehme an, Sie haben einen gültigen Grund, dies zu tun, aber es scheint ein bisschen falsch. Das heißt, hier ist ein Code, der das erreicht, was Sie tun wollen.

Wenn ich diesen Code ausführen, bekomme ich das zweite Element in der Liste.

+0

Bitte schauen Sie sich "answer" an, wo ich erklärt habe, dass in invoke nur der Verweis auf den oObjectType (nicht oListType01) verwendet werden kann. – milan

+0

Ich habe den Code so geändert, dass er auf die Referenz aufruft. Das sollte es tun. –

+0

Das hat bei mir funktioniert, danke! Nur eine Anmerkung: Der erste Parameter von mInfo.Invoke() kann null sein. Wir rufen eine statische Methode auf, keine Methode für eine Instanzmethode. –

0

Die ElementAt-Erweiterungsmethode ist wahrscheinlich auf IEnumerable <T> und so, wenn Sie Ihre Liste wie ein Objekt behandeln, wird die Erweiterungsmethode nicht verfügbar sein, wenn Sie es umwandeln. Entweder ((Liste <MyClass01>) oObjectType) .ElementAt() oder (oObjectType als Liste <MyClass01>) .ElementAt().

Ich muss jedoch mit allem Respekt fragen, warum Sie das jemals machen wollen? Es fällt mir auf, dass hier etwas nicht stimmt, das über Schnittstellen etwas sauberer gemacht werden könnte.

+0

'IEnumerable' Extension-Methoden sind in der' System.Linq.Enumerable' Klasse. –

+0

Von System.Linq.Enumerable. . . öffentliche statische TSource ElementAt (diese IEnumerable Quelle, Index int) {...} –

+0

Bitte werfen Sie einen Blick auf Antwort oben, wo ich die Einschränkungen erläutert. – milan

0

Wenn wir das mit Sicherheit davon ausgehen kann:

  • oObjectType ist ein IEnumerable von einigen T

dann ist hier der Code die Elemente daraus zu extrahieren.

Bitte beachte, dass ich ernsthaft fragen, ob dies der richtige Weg, um darüber zu gehen, aber Sie haben uns nicht genügend Informationen gegeben Ihnen helfen herauszufinden, ob es eine bessere Art und Weise ist, so dass alle mit dem wir links ist beantworte die Frage einfach wie gefragt.

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

Das ist wirklich ähnlich wie Ihre other question, aber in diesem Fall werden die statischen ElementAt Verfahren erfordern tatsächlich zwei Parameter. Versuchen Sie Folgendes:

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

Verwandte Themen