Отражение: вызов метода с общим списком в результате - PullRequest
4 голосов
/ 27 января 2012

У меня есть следующий пример-класс:

public class MyClass<T>
{
    public IList<T> GetAll()
    {
        return null; // of course, something more meaningfull happens here...
    }
}

И я хотел бы вызвать GetAll с отражением:

Type myClassType = typeof(MyClass<>);
Type[] typeArgs = { typeof(object) };
Type constructed = myClassType.MakeGenericType(typeArgs);
var myClassInstance = Activator.CreateInstance(constructed);

MethodInfo getAllMethod = myClassType.GetMethod("GetAll", new Type[] {});
object magicValue = getAllMethod.Invoke(myClassInstance, null);

В результате (в последней строке кода выше):

Операции с поздним связыванием не могут быть выполнены для типов или методов, для которых ContainsGenericParameters имеет значение true.

Хорошо, вторая попытка:

MethodInfo getAllMethod = myClassType.GetMethod("GetAll", new Type[] {});
getAllMethod = getAllMethod.MakeGenericMethod(typeof(object));
object magicValue = getAllMethod.Invoke(myClassInstance, null);

В результате (во второй последней строке кода выше):

System.Collections.Generic.IList`1 [T] GetAll () не является GenericMethodDefinition. MakeGenericMethod может быть вызван только для метода, для которого MethodBase.IsGenericMethodDefinition имеет значение true.

Что я здесь не так делаю?

Ответы [ 4 ]

6 голосов
/ 27 января 2012

Я пробовал это, и это работает:

// Create generic type
Type myClassType = typeof(MyClass<>);
Type[] typeArgs = { typeof(object) };   
Type constructed = myClassType.MakeGenericType(typeArgs);

// Create instance of generic type
var myClassInstance = Activator.CreateInstance(constructed);    

// Find GetAll() method and invoke
MethodInfo getAllMethod = constructed.GetMethod("GetAll");
object result = getAllMethod.Invoke(myClassInstance, null); 
1 голос
/ 27 января 2012

Это работает:

 public static void TestMethod()
 {
     Type myClassType = typeof(MyClass<>);
     Type[] typeArgs = { typeof(object) };
     Type constructed = myClassType.MakeGenericType(typeArgs);
     var myClassInstance = Activator.CreateInstance(constructed);

     MethodInfo getAllMethod = constructed.GetMethod("GetAll", new Type[] { });
     object magicValue = getAllMethod.Invoke(myClassInstance, null);
 }

В вашем коде есть следующие ошибки:

  • Вам необходимо вызвать GetMethod(...) для объекта типа вашего универсального класса(не в экземпляре).
  • getAllMethod.Invoke(...) требуется экземпляр универсального класса, который вы создали с помощью Activator.
1 голос
/ 27 января 2012

Я заметил (не уверен, что это просто ошибка в вашем примере), что есть проблема с вашим кодом. myClassInstance будет иметь тип object, поэтому вы не можете вызвать GetMethod(...) для него. Я думаю, что вы можете вместо этого называть это типом. Во-вторых, вы передаете baseRepo в качестве объекта для вызова метода - конечно, вы хотите вызвать метод при создании экземпляра типа - в этом случае, переменная myClassInstance?

Если вы измените свой код таким образом, у вас должен получиться что-то вроде приведенного ниже кода (который при тестировании работает):

Type classType = typeof(MyClass<>);
Type[] typeArgs = { typeof(object) };
Type fullClassType = classType.MakeGenericType(typeArgs);

var classInstance = Activator.CreateInstance(fullClassType);

MethodInfo method = fullClassType.GetMethod("GetAll", new Type[0]);
object result = method.Invoke(classInstance, null);
0 голосов
/ 27 января 2012

Если это то, как вы используете его, почему вы пытаетесь сделать MyClass универсальным?Это будет значительно быстрее:

public class MyClass
{
    public IList GetAll()
    {
        return null; // of course, something more meaningfull happens here...
    }
}

, а затем просто позвоните

var myObject = new MyClass();
var myList = myObject.GetAll();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...