【问题标题】:Converting a 2 Argument Expression into a 1 Argument Expression将 2 参数表达式转换为 1 参数表达式
【发布时间】:2019-03-03 23:39:02
【问题描述】:

假设我有一个Expression<Func<Arg1,Arg2,ReturnType>>,如何将其转换为Expression<Func<Arg1,ReturnType>>

我已经定义了一个Expression<Func<Individual, Record, bool>>,如果允许个人查看记录,它将返回true。我想在我的 DbContext 的 Where 子句中为个人或记录使用这个表达式。示例:

Expression<Func<Individual,Record,bool>> expression = GetFilterExpression();

// Get All the records that an individual can review...
Individual ind = SomeIndividual();
Expression<Func<Individual,bool>> canBeViewedBy = Utility.ReplaceParameter(expression, 0, ind);
List<Record> records = _context.Records.Where(canBeViewedBy).ToList();

// Get All the individuals that can review the record...
Record record = SomeRecord();
Expression<Func<Record,bool>> canView = Utility.ReplaceParameter(expression, 1, record);
List<Individual> individuals = _context.Individuals.Where(canView).ToList();

在我的实际应用程序中,我有一个CanIndividualViewRecordSpecification,它当前生成一个Expression&lt;Func&lt;Record,bool&gt;&gt;。我希望它也能够生成Expression&lt;Func&lt;Individual,bool&gt;&gt;,而不必多次定义过滤器。

【问题讨论】:

    标签: c# entity-framework linq functional-programming


    【解决方案1】:

    我最终自己解决了。

    public static class ExpressionHelpers
    {
        public static Expression<Func<TArg2, TReturn>> ReplaceParamter<TArg1, TArg2, TReturn>(this Expression<Func<TArg1, TArg2, TReturn>> source, TArg1 arg1)
        {
            var t1Param = Expression.Constant(arg1);
            var t2Param = Expression.Parameter(typeof(TArg2));
            var body = source.Body
                        .ReplaceParameter(source.Parameters[0], t1Param)
                        .ReplaceParameter(source.Parameters[1], t2Param);
            return Expression.Lambda<Func<TArg2, TReturn>>(body, t2Param);
        }
    
        public static Expression<Func<TArg1, TReturn>> ReplaceParamter<TArg1, TArg2, TReturn>(this Expression<Func<TArg1, TArg2, TReturn>> source, TArg2 arg2)
        {
            var t1Param = Expression.Parameter(typeof(TArg1));
            var t2Param = Expression.Constant(arg2);
            var body = source.Body
                        .ReplaceParameter(source.Parameters[0], t1Param)
                        .ReplaceParameter(source.Parameters[1], t2Param);
            return Expression.Lambda<Func<TArg1, TReturn>>(body, t1Param);
        }
    
    
        public static Expression ReplaceParameter(this Expression expression,
            ParameterExpression toReplace,
            Expression newExpression)
        {
            return new ParameterReplaceVisitor(toReplace, newExpression)
                .Visit(expression);
        }
    }
    
    
    public class ParameterReplaceVisitor : ExpressionVisitor
    {
        private ParameterExpression from;
        private Expression to;
        public ParameterReplaceVisitor(ParameterExpression from, Expression to)
        {
            this.from = from;
            this.to = to;
        }
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return node == from ? to : base.VisitParameter(node);
        }
    }
    

    例子:

    Expression<Func<Individual,Record,bool>> expression = GetFilterExpression();
    
    // Get All the records that an individual can review...
    Individual ind = SomeIndividual();
    Expression<Func<Record,bool>> canBeViewedBy = expression.ReplaceParameter(ind);
    List<Record> records = _context.Records.Where(canBeViewedBy).ToList();
    
    // Get All the individuals that can review the record...
    Record record = SomeRecord();
    Expression<Func<Individual,bool>> canView = expression.ReplaceParameter(record);
    List<Individual> individuals = _context.Individuals.Where(canView).ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-09
      • 2015-09-09
      • 2013-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多