2009-12-22 11 views
6

Tengo el problema de que después de crear el objeto "oListType01" del tipo List < MyClass01> y después de asignarlo al otro objeto "oObjectType" de tipo "objeto" no puedo acceder a ninguna función más "ElementAt (1)". Intenté usar la reflexión, pero siempre obtengo una excepción (conflicto de parámetros) en el método "Invocar". ¿Alguien sabe por qué? Milán¿Cómo llamar al método de extensión "ElementAt" de la lista <T> con la reflexión?

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; 

Desde aquí fowrads única oObjectType objeto está disponible (al alza sucede en la llamada de función separada en el caso real). En VS oObjectType muestra dos elementos a los que me gustaría acceder por reflexión.

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

¿Por qué lo asignas a un objeto en primer lugar? Si por algún motivo, y si sabe en tiempo de compilación, qué tipo de la lista siempre contendrá instancias de MyClass01, ¿por qué no la vuelve a enviar a una lista , como esta: ((List ) oObjectType) .ElementAt (1); – tclem

+0

plese echa un vistazo a "respuesta", donde expliqué que en invocación solo se puede usar referencia al oObjectType (no oListType01 y no MyClass01). – milan

Respuesta

9

Supongo que tiene un motivo válido para hacer esto, pero parece un poco mal. Eso dicho aquí es un código que logrará lo que estás tratando de hacer.

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

Cuando ejecuto este código, obtengo el segundo elemento en la Lista.

+0

plese echa un vistazo a "respuesta", donde expliqué que en invocación solo se puede usar referencia al oObjectType (no oListType01). – milan

+0

Cambié el código para que invoque en la referencia. Deberias hacer eso. –

+0

Esto funcionó para mí, gracias! Solo una nota: el primer parámetro para mInfo.Invoke() puede ser nulo. Estamos llamando a un método estático, no a un método en un método de instancia. –

0

El método de extensión ElementAt probablemente está en IEnumerable <T> y por eso, cuando trata su lista como un objeto, el método de extensión no estará disponible a menos que lo lance. O bien ((Lista <MyClass01>) oObjectType) .ElementAt() o (oObjectType como List <MyClass01>) .ElementAt().

Tengo que preguntar, sin embargo, con el debido respeto por qué alguna vez querrías hacer esto en primer lugar? Me sorprende que haya algo mal aquí que podría hacerse un poco más limpio usando interfaces.

+0

Los métodos de extensión 'IEnumerable' están en la clase' System.Linq.Enumerable'. –

+0

desde System.Linq.Enumerable. . . elemento TSource público estáticoEn (este IEnumerable fuente, índice int) {...} –

+0

eche un vistazo a la respuesta anterior, donde le expliqué las limitaciones. – milan

0

Si podemos suponer con seguridad que:

  • oObjectType es un IEnumerable de algunas T

entonces aquí es el código para extraer los artículos de la misma.

Tenga en cuenta que en serio me pregunto si este es el derecho manera de hacerlo, pero no nos ha dado suficiente información para ayudarlo a determinar si hay una mejor manera, entonces todo lo que nos queda es solo respondiendo la pregunta como se le preguntó.

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

Esto es muy similar a su other question, pero en este caso, el método ElementAt estática es en realidad que requiere dos parámetros. Pruebe esto:

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

Cuestiones relacionadas