Проблема выражения LINQ - PullRequest
       1

Проблема выражения LINQ

1 голос
/ 14 августа 2011

У меня есть выражение Linq, которое вызывает у меня настоящую головную боль, и надеюсь, что кто-нибудь может помочь мне выяснить, почему моему провайдеру это не нравится.

Если я сделаю следующее, то все будет работать нормально;

Expression<Func<Employee, bool>> expr = e => e.Participant == "Y";
_context.Employees.Where(expr).ToList<IEmployee>();

Однако, если я сделаю следующее, моему провайдеру это не понравится.

Expression<Func<IEmployee, bool>> expr = e => e.Participant == "Y";

Expression<Func<Employee, bool>> convertedExpr = ParameterReplacer.Replace
          <Func<IEmployee, bool>, Func<Employee, bool>> 
          (expr,
          expr.Parameters.Single(), 
          Expression.Parameter(typeof(Employee)));

_context.Employees.Where(convertedExpr).ToList<IEmployee>();

Причина, по которой я выполняю преобразование, заключается в том, что верхний уровень моего приложения знает только о типе интерфейсапоэтому я преобразую его в выражение, которое использует конкретный тип на нижнем уровне, используя ParameterReplacer (любезно предоставленный другим членом SO).

Я сравнил выражения linq между работающей версией итот, который не имеет, и единственное отличие, которое я вижу, в том, что я вижу в свойстве DebugView в том, что имена параметров отличаются.

Вот код для ParameterReplacer;

public static class ParameterReplacer
{
    // Produces an expression identical to 'expression'
    // except with 'source' parameter replaced with 'target' parameter.
    public static Expression<TOutput> Replace<TInput, TOutput>(Expression<TInput> expression, ParameterExpression source, ParameterExpression target)
    { 
        return new ParameterReplacerVisitor<TOutput>(source, target).VisitAndConvert(expression);
    } 

    private class ParameterReplacerVisitor<TOutput> : ExpressionVisitor
    {         
        private ParameterExpression _source;
        private ParameterExpression _target;

        public ParameterReplacerVisitor(ParameterExpression source, ParameterExpression target)
        {             
            _source = source; 
            _target = target;
        } 

        internal Expression<TOutput> VisitAndConvert<T>(Expression<T> root)
        {             
            return (Expression<TOutput>)VisitLambda(root);
        }          

        protected override Expression VisitLambda<T>(Expression<T> node)
        {             
            // Leave all parameters alone except the one we want to replace.
            var parameters = node.Parameters.Select(p => p == _source ? _target : p);
            return Expression.Lambda<TOutput>(Visit(node.Body), parameters);
        }          

        protected override Expression VisitParameter(ParameterExpression node)
        { 
            // Replace the source with the target, visit other params as usual.
            return node == _source ? _target : base.VisitParameter(node);
        }
    } 
}

Это проблема с ParameterReplacer или моим провайдером?Может ли кто-нибудь мне помочь?

Используемый мной провайдер - Telerik OpenAccess, исключение составляет:

InnerException: System.NullReferenceException Message = Ссылка на объект не установлена ​​наэкземпляр объекта.Source = Telerik.Тип type, Int32 elementAt, Object [] groupResolutionParamValues, логический одиночный, логический checkOid) InnerException:

1 Ответ

1 голос
/ 14 августа 2011

Я никогда не пользовался вашим провайдером, поэтому я не уверен, но, учитывая обстоятельства, я думаю, что это хорошая ставка:

Поскольку единственное различие заключается в том, что параметр во втором выражении имеет значение null Name, а полученное вами исключение - исключение с нулевой ссылкой, я думаю, что это именно та проблема. Попробуйте изменить Name на ненулевое значение.

Это означает изменение создания нового параметра на что-то вроде:

Expression.Parameter(typeof(Employee), "e")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...