【问题标题】:How to create an anonymous object as a LINQ Expression如何创建匿名对象作为 LINQ 表达式
【发布时间】:2018-10-18 12:24:33
【问题描述】:

我想在 C# 中使用表达式树创建以下 lambda 表达式:

var result = dataList.GroupBy(x => new { x.Prop1, x.Prop2 })

如何将具有两个属性的匿名类型作为 LINQ 表达式 (lambdaExp)?

这是我目前得到的:

IQueryable<GraphData> queryableData = graphDataList.AsQueryable();
ParameterExpression pe = Expression.Parameter(typeof(GraphData), "x");

Expression prop1 = Expression.PropertyOrField(pe, "Prop1");
Expression prop2 = Expression.PropertyOrField(pe, "Prop2");

var lambdaExp = Expression.Lambda<Func<GraphData, object>>( new { prop1, prop2 } , pe);     //doesn't compile

MethodCallExpression groupByCallExpression = Expression.Call(
    typeof(Queryable),
    "GroupBy",
    new Type[] { typeof(GraphData), typeof(object) }, 
    queryableData.Expression,
    lambdaExp);

IQueryable<GraphData> result = queryableData.Provider.CreateQuery<GraphData>(groupByCallExpression);

【问题讨论】:

  • 你已经尝试了什么?显示你的负担和你被困在哪里。否则我们只能猜测您的问题可能是什么。
  • 这个答案可能会解决您的问题:stackoverflow.com/a/17694121/361842

标签: c# linq lambda expression


【解决方案1】:

当您编写 linq 查询和匿名对象时,编译器隐藏了它正在为您做的许多魔法。特别是对于匿名对象,它还为您创建新类型。除非该类型存在于某处,否则您将需要手动创建该类型并在其位置使用该类型。

你可以作弊,让编译器创建一个具有该类型的对象并保存对该类型的引用。这样,您就可以生成必要的表达式来实例化该对象。

需要注意的一点是,为您创建的匿名对象将具有按定义顺序提供参数的构造函数,因此您只需要调用该构造函数即可。

var keyType = new { Prop1=default(string), Prop2=default(string) }.GetType();
var ctor = keyType.GetConstructor(new Type[] { typeof(string), typeof(string) });
var param = Expression.Parameter(typeof(GraphData), "x");
var keySelector = Expression.Lambda(
    Expression.New(ctor,
        Expression.PropertyOrField(param, "Prop1"), // corresponds to Prop1
        Expression.PropertyOrField(param, "Prop2")  // corresponds to Prop2
    ),
    param
); // returns non-generic LambdaExpression

请记住,我们处理的是编译时未知的类型,因此您的键选择器表达式将没有编译时类型。

【讨论】:

    猜你喜欢
    • 2016-12-25
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    相关资源
    最近更新 更多