I два дерева выражений определены следующим образом:
private Expression<Func<TEntity, TPropertyResult>> PropertyAccessor { get; set; }
и
private Expression<Func<TPropertyResult, bool>> TestExpression { get; set; }
Мне нужно создать новое дерево выражений, которое приведет к эквиваленту:
var expression = p => this.TestExpression(this.PropertyAccessor(p));
При использовании Expression.Invoke (this.TestExpression, this.PropertyAccessor )
, я получаю следующую ошибку
{"Выражение типа 'System.Func`2 [MyEntity, System.String]' не может использоваться для параметра типа { {1}} 'System.String' "}
TPropertyResult
- это строка во время моего теста.
Я пробовал использовать Expression.Call
или Expression.Invoke
. Не повезло. Что мне использовать?
Я думаю, что это делает то, о чем вы просите:
Expression<Func<TEntity, bool>> Combined
{
get
{
var entity = Expression.Parameter(typeof(TEntity));
var pa = Expression.Invoke(PropertyAccessor, entity);
var te = Expression.Invoke(TestExpression, pa);
return (Expression<Func<TEntity, bool>>) Expression.Lambda(te, entity);
}
}
Я тестировал это, и он работает так, как я ожидал.
Однако, перечитывая ваш исходный вопрос (до того, как я редактировал), у меня складывается впечатление, что вы задали неправильный вопрос и что вам, вероятно, не нужны деревья выражений. Если все, что вам нужно, это функции , то вы можете использовать их без Выражение
:
private Func<TEntity, TPropertyResult> PropertyAccessor { get; set; }
private Func<TPropertyResult, bool> TestExpression { get; set; }
private Func<TEntity, bool> Combined
{
get
{
return entity => TestExpression(PropertyAccessor(entity));
}
}
Пример использования:
// Set up the original functions
PropertyAccessor = entity => GenerateResult(entity);
TestExpression = result => result.IsCool();
// This stores a reference to the combined function
var fn = Combined;
// This actually evaluates the function
bool isCool = fn(myEntity);
// Alternatively, you could evaluate the function directly, without the variable
bool isCool = Combined(myEntity);