Динамическая проекция с использованием DynamicExpressionParser ParseLambda - PullRequest
0 голосов
/ 17 июня 2019

Я пытаюсь преобразовать некоторый код, который создает динамическую проекцию из .Net 4.5 в .Net Core 3;У меня есть следующий код в .Net 4.5

var e = DynamicExpression.ParseLambda(
                typeof(MyModel),
                typeof (object),
                "new(Id as id)");

ParseLambda недоступен на DynamicExpression в .Net Core 3, поэтому я изменил код на:

var e = DynamicExpressionParser.ParseLambda(
            typeof(MyModel),
            typeof (object),
            "new(Id as id)");

Но это приводит кисключение нулевой ссылки со следующей трассировкой стека

   at System.Linq.Dynamic.Core.Parser.ExpressionParser.CreateNewExpression(List`1 properties, List`1 expressions, Type newType)
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseNew()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIdentifier()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimary()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseUnary()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseMultiplicative()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAdditive()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseShiftOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseComparisonOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLogicalAndOrOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIn()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAndOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseOrOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLambdaOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseNullCoalescingOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseConditionalOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.Parse(Type resultType, Boolean createParameterCtor)
   at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParsingConfig parsingConfig, Boolean createParameterCtor, ParameterExpression[] parameters, Type resultType, String expression, Object[] values)
   at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(Boolean createParameterCtor, Type itType, Type resultType, String expression, Object[] values)
   at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(Type itType, Type resultType, String expression, Object[] values)

Код работает нормально, когда выражением является "Id == 0" или любое другое сравнение, но я не могу заставить работать "новое" выражение ...

Ответы [ 2 ]

1 голос
/ 18 июня 2019

Передача typeof (объект) в качестве типа результата работает с реализацией .Net 4.5 ParseLambda, но после просмотра исходного кода System.Linq.Dynamic.Core я обнаружил, что ParseLambda может принимать тип результата null. Следующий код работает как положено в .Net Core 3.

var e = DynamicExpressionParser.ParseLambda(
          typeof(MyModel),  // itType
          null,             // resultType
          "new(Id as id)"); // expression

https://github.com/StefH/System.Linq.Dynamic.Core/blob/master/src/Microsoft.EntityFrameworkCore.DynamicLinq/EFDynamicQueryableExtensions.cs

0 голосов
/ 18 июня 2019

Похоже, вы используете System.Linq.Dynamic.Core .

В этом случае вам необходимо убедиться, что тип вывода получает свойство id.Ваш код не будет работать, потому что ваш тип вывода object.Поскольку object не получает id свойство , оно завершается ошибкой.

По аналогичной причине вам также необходимо убедиться, что тип ввода получает свойствоиз Id.

В фокусе всегда используются непротиворечивые свойства.Например, допустим, у вас есть два типа:

public class MyInput                  // input 
{
    public int Id { get; set; }
}

public class MyOutput                // output
{
    public int id { get; set; }
}

Вы можете проанализировать строку, как показано ниже:

var e = DynamicExpressionParser.ParseLambda(
    typeof(MyInput),                 // input type
    typeof(MyOutput),                // output type
    "new (Id as id)");               // initialize properties

// test
MyOutput o = e.Compile().DynamicInvoke(new MyInput() { Id = 123 }) as MyOutput;
Console.WriteLine(o.id);     // outputs 123
...