Как вызвать метод через отражение с лямбда-выражением в качестве параметра? - PullRequest
5 голосов
/ 12 января 2009

Я хочу сделать это:

MethodInfo m = myList.GetType().GetMethod("ConvertAll", System.Reflection.BindingFlags.InvokeMethod).MakeGenericMethod(typeof(object));
List<object> myConvertedList = (List<object>)m.Invoke(myList, new object[]{ (t => (object)t)});

myList - это общий список определенного типа (неизвестный приложению), и я хочу преобразовать его в список объектов для выполнения некоторых операций.

Однако эта ошибка завершается с этой ошибкой: «Невозможно преобразовать лямбда-выражение в тип« объект », потому что это не тип делегата»

Можете ли вы помочь мне найти, что не так? Я пытаюсь сделать что-то, что невозможно?

Есть ли другой способ добиться того же?

Ответы [ 2 ]

5 голосов
/ 12 января 2009

Лямбда-выражение может быть преобразовано либо в тип делегата, либо в дерево выражений с правильной подписью, но вам нужно указать, какой это тип делегата.

Я думаю, ваш код будет намного проще, если вы сделаете этот метод универсальным:

public static List<object> ConvertToListOfObjects<T>(List<T> list)
{
    return list.ConvertAll<object>(t => t);
}

Тогда вам просто нужно найти и вызвать этот метод в общем:

MethodInfo method = typeof(Foo).GetMethod("ConvertToListOfObjects",
    BindingFlags.Static | BindingFlags.Public);
Type listType = list.GetType().GetGenericArguments()[0];
MethodInfo concrete = method.MakeGenericMethod(new [] { listType });
List<object> objectList = (List<object>) concrete.Invoke(null, 
                                                   new object[]{list});

Полный пример:

using System;
using System.Reflection;
using System.Collections.Generic;

class Test
{
    public static List<object> ConvertToListOfObjects<T>(List<T> list)
    {
        return list.ConvertAll<object>(t => t);
    }

    static void Main()
    {
        object list = new List<int> { 1, 2, 3, 4 };

        MethodInfo method = typeof(Test).GetMethod("ConvertToListOfObjects",
            BindingFlags.Static | BindingFlags.Public);
        Type listType = list.GetType().GetGenericArguments()[0];
        MethodInfo concrete = method.MakeGenericMethod(new [] { listType });
        List<object> objectList = (List<object>) concrete.Invoke(null,
                                                    new object[] {list});

        foreach (object o in objectList)
        {
            Console.WriteLine(o);
        }
    }
}
1 голос
/ 12 января 2009

Лямбда формирует метод group (в основном это метод, идентифицируемый только именем (и областью действия). Поскольку методы с одинаковым именем могут быть перегружены, группа методов состоит из нескольких различных членов). Это не всегда может быть неявно преобразовано в делегат, потому что делегат фактически связан с одним методом из группы методов. Это играет роль при перегрузке.

К сожалению, то же самое относится и к вашему случаю. Средство защиты - сделать явного делегата:

List<object> myConvertedList = (List<object>)m.Invoke(myList, new object[]{ new Func<YourType, object>(t => (object)t)});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...