È possibile utilizzare le seguenti funzioni di assistenza (si potrebbe probabilmente dare loro un nome migliore , ma non è indispensabile):
public static class ExpressionUtils
{
public static Expression<Func<TOuter, TResult>> Bind<TOuter, TInner, TResult>(this Expression<Func<TOuter, TInner>> source, Expression<Func<TInner, TResult>> resultSelector)
{
var body = new ParameterExpressionReplacer { source = resultSelector.Parameters[0], target = source.Body }.Visit(resultSelector.Body);
var lambda = Expression.Lambda<Func<TOuter, TResult>>(body, source.Parameters);
return lambda;
}
public static Expression<Func<TOuter, TResult>> ApplyTo<TInner, TResult, TOuter>(this Expression<Func<TInner, TResult>> source, Expression<Func<TOuter, TInner>> innerSelector)
{
return innerSelector.Bind(source);
}
class ParameterExpressionReplacer : ExpressionVisitor
{
public ParameterExpression source;
public Expression target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == source ? target : base.VisitParameter(node);
}
}
}
Let vedere come l'espressione di esempio
c.Criteria = x => x.Name.StartsWith("SomeTexts");
può essere costruito da due parti differenti.
Se hai
Expression<Func<Customer, string>> e = x => x.Name;
poi
c.Criteria = e.Bind(x => x.StartsWith("SomeTexts"));
o se si dispone di questo, invece
Expression<Func<string, bool>> e = x => x.StartsWith("SomeTexts");
poi
c.Criteria = e.ApplyTo((Customer x) => x.Name);
Se si dispone di entrambe le espressioni, è possibile utilizzare una delle due funzioni, poiché a.Bind(b)
equivale a b.ApplyTo(a)
.
È 'p' un 'espressione>' o un 'Func '? –
gmiley
Non dovrebbe 'c.Criteria = x.Name.StartWith (" SomeTexts ");' be 'c.Criteria = x => x.Name.StartWith (" SomeTexts ");'? –
@YacoubMassad: hai ragione :) – Masoud