Как конвертировать выражение> к выражению>? - PullRequest
0 голосов
/ 22 мая 2018

У меня есть выражение, которое принимает параметр типа object.Мне нужно создать типизированное выражение во время выполнения, используя переменную Type.Увидеть ниже.Параметр должен иметь тип int, так что я получаю Expression<Action<Program, int>>, который для данного int вызывает нетипизированный метод Set.Как это можно сделать?

class Program
{
    private static Type SomeRuntimeType() => typeof(int);

    public void Set(object v)
    {
        Debug.WriteLine("Setting value...");
    }

    static void Main(string[] args)
    {
        Expression<Action<Program, object>> e1 = (t, v) => t.Set(v);

        var type = SomeRuntimeType();
        // TODO: Create typed expression...
        Expression<Action<Program, type>> e2 = ...
    }
}

1 Ответ

0 голосов
/ 22 мая 2018

Простое решение: с точки зрения C #, лямбда-выражение нетипизировано (оно имеет тип LambdaExpression).Во время выполнения он имеет «правильный тип» (например, Expression<Action<Program, T2>>, это возможно, потому что Expression<T> подклассы LambdaExpression)

Expression<Action<Program, object>> e1 = (t, v) => t.Set(v);

var type = typeof(int);
var par1 = e1.Parameters[0];
var par2 = Expression.Parameter(type);

// if type is a value type, you have to expressly box it 
Expression conv = type.IsValueType ? (Expression)Expression.Convert(par2, typeof(object)) : par2;

// We "chain" the two expressions
InvocationExpression invoke = Expression.Invoke(e1, par1, conv);
LambdaExpression lambda = Expression.Lambda(invoke, par1, par2);

var compiled = lambda.Compile();

// sanity check, 
bool lambdaTypeIsExpected = typeof(Expression<>).MakeGenericType(typeof(Action<,>).MakeGenericType(typeof(Program), type)) == lambda.GetType();

Обратите внимание, что если вам нужен LambdaExpression для некоторого ORM иликакая-то другая подсистема, не все библиотеки поддерживают Invoke (которую можно удалить с помощью средства переписывания выражений) или Convert (что необходимо для преобразования из типа значения в ссылочный тип).Я даже видел библиотеки, которым не нравится object full-stop (я уже пробовал эти приемы несколько раз :-))

...