Использование выражения в выражении LINQ - PullRequest
0 голосов
/ 22 января 2019

Я использую деревья выражений LINQ для генерации динамического кода.

В этом коде мне нужно обернуть немного BlockExpression в оператор using, например:

using(GetLock()) {
  return ...SomeExpr...;
}

Нет Expression.Using, и я не уверен, как правильно создавать переменные для Expression.TryFinally

1 Ответ

0 голосов
/ 22 января 2019

Вам нужно создать код, похожий на

IDisposable disposable;
try
{
  disposable = GetLock();
  // rest of using block
}
finally
{
  if (disposable != null)
    disposable.Dispose();
}

Следующий метод создаст это выражение

private static Expression<Action> CreateExpression<T>(Expression<Func<T>> getLock) where T : IDisposable
{
    var disposableType = typeof(IDisposable);
    var dispose = disposableType.GetMethod("Dispose");
    if (dispose == null)
        throw new InvalidOperationException();

    var disposable = Expression.Variable(disposableType, "disposable");
    var tryFinally = Expression.TryFinally(
        Expression.Block(
            Expression.Assign(disposable, Expression.Convert(Expression.Invoke(getLock), disposableType))
            // rest of using block
        ),
        Expression.IfThen(
            Expression.NotEqual(disposable, Expression.Constant(null)),
            Expression.Call(disposable, dispose)
        )
    );

    var lambda = Expression.Lambda<Action>(
      Expression.Block(
        new []{disposable}, // variable
        tryFinally // body
      )
    );

    return lambda;
}    
...