Подтвердить что ты не робот

Как вызвать общий метод с заданным объектом типа?

Я хочу вызвать свой общий метод с заданным объектом типа.

void Foo(Type t)
{
     MyGenericMethod<t>();
}

очевидно, не работает.

Как я могу заставить его работать?

4b9b3361

Ответ 1

Ваш образец кода не будет работать, потому что общий метод ожидает идентификатор типа, а не экземпляр класса Type. Для этого вам нужно использовать отражение:

public class Example {

    public void CallingTest()
    {
        MethodInfo method = typeof (Example).GetMethod("Test");
        MethodInfo genericMethod = method.MakeGenericMethod(typeof (string));
        genericMethod.Invoke(this, null);

    }

    public void Test<T>()
    {
        Console.WriteLine(typeof (T).Name);
    }
}

Имейте в виду, что это очень хрупкое, я бы предпочел найти другой шаблон, чтобы вызвать ваш метод.

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

public class Example {

    public void CallingTest()
    {
        MethodInfo method = GetMethod<Example>(x => x.Test<object>());
        MethodInfo genericMethod = method.MakeGenericMethod(typeof (string));
        genericMethod.Invoke(this, null);

    }

    public static MethodInfo GetMethod<T>(Expression<Action<T>> expr)
    {
        return ((MethodCallExpression) expr.Body)
            .Method
            .GetGenericMethodDefinition();
    }

    public void Test<T>()
    {
        Console.WriteLine(typeof (T).Name);
    }
}

Обратите внимание на передачу идентификатора типа "объект" в качестве аргумента общего типа в лямбда. Не удалось так быстро разобраться, как обойти это. В любом случае, я думаю, это безопасно для компиляции. Он как-то чувствует себя не так:/

Ответ 2

Вам нужно использовать отражение, к сожалению (по причинам, о которых говорил Джаред). Например:

MethodInfo method = typeof(Foo).GetMethod("MyGenericMethod");
method = method.MakeGenericMethod(t);
method.Invoke(this, new object[0]);

Очевидно, что вам нужно больше проверки ошибок:)


Боковое примечание: мой локальный MSDN не указывает, что параметр из MakeGenericMethod является массивом параметров, поэтому я ожидал, что потребуется:

method = method.MakeGenericMethod(new Type[] { t });

но, похоже, это массив параметров в реальности, и онлайн-документы MSDN согласны. Одд.

Ответ 3

Этот подход не будет работать. Причина в том, что Type является объектом, тип которого определяется во время выполнения. Однако вы пытаетесь использовать его для вызова общего метода. Во время компиляции устанавливается общий тип вызова метода. Следовательно, объект типа никогда не может использоваться для параметра типа для общего метода.