2016-09-21 4 views
1

Я хотел бы, чтобы произвести это предложение с помощью деревьев выражений:Expression Tree для о .Value

o?.Value 

o является экземпляром класса, какой бы ни.

Есть ли способ?

+1

Вы прочитали это? http://stackoverflow.com/questions/28880025/why-cant-i-use-the-null-propagation-operator-in-lambda-expressions –

+0

Я имел в виду использование методов Expression.constructors-like. – Jordi

ответ

4

Обычно, если вы хотите сделать, как построить дерево выражений для некоторого выражения, вы позволяете компилятору C# делать это и проверять результат.

Но в этом случае это не сработает, потому что «Лямбда дерева выражений не может содержать нулевой оператор распространения». Но на самом деле вам не нужен оператор, распространяющий нуль, вам просто нужно что-то, что ведет себя как одно.

Вы можете сделать это, создав выражение, которое выглядит так: o == null ? null : o.Value. Код:

public Expression CreateNullPropagationExpression(Expression o, string property) 
{ 
    Expression propertyAccess = Expression.Property(o, property); 

    var propertyType = propertyAccess.Type; 

    if (propertyType.IsValueType && Nullable.GetUnderlyingType(propertyType) == null) 
     propertyAccess = Expression.Convert(
      propertyAccess, typeof(Nullable<>).MakeGenericType(propertyType)); 

    var nullResult = Expression.Default(propertyAccess.Type); 

    var condition = Expression.Equal(o, Expression.Constant(null, o.Type)); 

    return Expression.Condition(condition, nullResult, propertyAccess); 
} 
+0

Как и 'o == null? null: o.Value', и в отличие от 'o? .Value', это приведет к тому, что' o' будет оцениваться дважды, если скомпилировано в IL, правильно? Если это так, то, вероятно, следует упомянуть. – hvd

+2

@hvd Да. Я молча предполагал, что это нормально, так как оценка простого выражения типа 'o' дважды не должна вызывать никаких проблем. Если вы хотите этого избежать, вы можете создать «Блок», который сначала присваивает 'o' временной переменной, а затем использует эту переменную. (Хотя это, вероятно, не сработает, если вы хотите использовать выражение с некоторым провайдером LINQ.) – svick

+0

Вы прокомментировали, что: если вы хотите сделать, как построить дерево выражений для некоторого выражения, вы даете компилятору C# сделать это и проверите result_. Я хотел бы попросить вас об этом. – Jordi

Смежные вопросы