Как создать Expression.Lambda, если тип неизвестен до времени выполнения?

Лучше всего это объяснить с помощью кода. У меня есть общий класс, у которого есть метод, возвращающий целое число. Вот простая версия для объяснения ...

public class Gen<T>
{
    public int DoSomething(T instance)
    {
        // Real code does something more interesting!
        return 1;
    }
}

Во время выполнения я использую отражение, чтобы обнаружить тип чего-либо, а затем хочу создать экземпляр моего класса Gen для этого конкретного типа. Это достаточно просто и делается так ...

Type fieldType = // This is the type I have discovered
Type genericType = typeof(Gen<>).MakeGenericType(fieldType);
object genericInstance = Activator.CreateInstance(genericType);

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

int answer = genericInstance.DoSomething(instance);

... за исключением того, что у меня нет «экземпляра» до некоторого момента позже во время выполнения, а genericInstance является сгенерированным типом, как можно увидеть выше. Моя попытка создать лямбда для этого выглядит следующим образом ...

MethodInfo mi = genericType.GetMethod("DoSomething", 
                                      BindingFlags.Instance | BindingFlags.Public);

var p1 = Expression.Parameter(genericType, "generic");
var p2 = Expression.Parameter(fieldType, "instance");

var x = Expression.Lambda<Func<genericType, fieldType, int>>
            (Expression.Call(p1, mi, p2), 
             new[] { p1, p2 }).Compile();

... чтобы позже я мог вызвать его примерно так ...

int answer = x(genericInstance, instance);

Конечно, вы не можете предоставить Func параметры экземпляра и так Я понятия не имею, как параметризовать генерацию лямбда. Есть идеи?

14
задан Phil Wright 18 October 2011 в 00:29
поделиться