Преобразование выражения 2 аргумента в выражение 1 аргумента - PullRequest
0 голосов
/ 28 сентября 2018

Если у меня есть Expression<Func<Arg1,Arg2,ReturnType>>, как мне преобразовать его в Expression<Func<Arg1,ReturnType>>?

Я уже определил Expression<Func<Individual, Record, bool>>, который возвращает значение true, если физическому лицу разрешено просматривать запись.Я хочу использовать это выражение в предложении Where в моем DbContext для отдельных лиц или записей.Пример:

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<Func<Record,bool>>.Я хочу, чтобы он также мог генерировать Expression<Func<Individual,bool>> без необходимости определять фильтр более одного раза.

1 Ответ

0 голосов
/ 28 сентября 2018

В итоге я решил ее самостоятельно.

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...