在 LINQ 查询中动态访问嵌套在匿名类型中的 属性

Dynamically access property nested in anonymous type within LINQ query

我正在我的 EF 映射数据库实体 类 上执行冗长的 LINQ 查询,该实体由 Linq2Sql 处理并以匿名类型结束:

...
.Where(e => ...)
.Join(..., (outer, inner) => new {
    outer.Object1,
    outer.TempId,
    Object2 = inner
})

到目前为止,一切都很好 - 到那时,一切都将很好地转换为数据库上的 SQL 和 运行。我可以迭代匿名类型的对象,此时只有其中包含的数据才会在 C# 端具体化。

但是: 我现在需要执行最后一个过滤步骤来减少数据集,这就是为什么它也应该在数据库上 运行。我需要比较 Object1Object2.

上的 属性

这个属性的名称作为字符串传入我的方法。

在正常情况下,这不会有问题。我可以简单地通过反射访问匿名对象——即使这意味着我必须通过 .GetType().GetGenericArguments()[0] 在我的可枚举对象上获取匿名类型。

但是,我需要确保此处的所有内容都是类型安全的,因此随后的 foreach 将让我迭代并使用匿名类型的实例。因此,创建过滤器表达式并不简单,因为我无法为 Lambda<TDelegate> 指定类型 - 它必须是 Func<..., Boolean>,其中 ... 是我的匿名类型!

我考虑过创建一个项目函数,而不是采用我的匿名类型中 Object1Object2 属于的类型的实例 - 例如,ObjectData,- 和returns 属性 值。这当然是可行的:

var prm = Expression.Parameter(typeof(ObjectData), "obj");
var projectionExpr = Expression.Lambda<Func<ObjectData, int>>(Expression.Property(prm, myPropertyName), prm);

但是我不确定在哪里应用它们 - 我需要某种“单项 select”,它只是通过投影表达式将一个值投影到另一个值,并且这将与 EF 的 LINQ to Entities/SQL 代一起很好地发挥作用 - 类似于(伪代码,具有虚构的 PROJECT 函数)这个:

.Select(info => new {
    info.Object1,
    info.TempId,
    info.Object2,
    Value1 = PROJECT(info.Object1, projectionExpr),
    Value2 = PROJECT(info.Object2, projectionExpr)
})

如何将最终过滤器添加到故事中?

这看起来更像是 dynamic linq 的情况。使用该库,应该可以将类似这样的内容添加到您的查询中:

.Where(e => ...)
.Join(..., (outer, inner) => new {
    outer.Object1,
    outer.TempId,
    Object2 = inner
})
.Where($"Object1.{myPropertyName} == Object2.{myPropertyName}");