使用DynamicExpressionParser ParseLambda进行动态投影

时间:2019-06-17 20:22:19

标签: c# linq asp.net-core projection

我正在尝试将一些创建可动态投影的代码从.Net 4.5转换为.Net Core 3;我在.Net 4.5中有以下代码

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

.net Core 3中的DynamicExpression上没有ParseLambda,因此我将代码更改为:

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 个答案:

答案 0 :(得分:1)

将typeof(object)作为结果类型传递与ParseLambda的.Net 4.5实现一起使用,但是在查看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

答案 1 :(得分:0)

听起来像您在使用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