我之前使用过基于 lamda 的 C# 表达式,但我没有手动编写它们的经验。 给定一个Expression> originalPredicate
,我想创建一个Expression> 翻译谓词
。
在这种情况下,SomeType 和 OtherType 具有相同的字段,但它们不相关(没有继承并且不基于公共接口)。
背景:我有一个基于 LINQ to SQL 的存储库实现。 我将 LINQ to SQL 实体投影到我的模型实体,以将我的模型保留在 POCO 中。 我想将表达式传递到存储库(作为规范的形式),但它们应该基于模型实体。 但我无法将这些表达式传递到数据上下文,因为它需要基于 LINQ to SQL 实体的表达式。
I have used C# expressions before based on lamdas, but I have no experience composing them by hand. Given an Expression<Func<SomeType, bool>> originalPredicate
, I want to create an Expression<Func<OtherType, bool>> translatedPredicate
.
In this case SomeType and OtherType have the same fields, but they are not related (no inheritance and not based on a common interface).
Background: I have a repository implementation based on LINQ to SQL. I project the LINQ to SQL entities to my Model entities, to keep my model in POCO. I want to pass expressions to the repository (as a form of specifications) but they should be based on the model entities. But I can't pass those expressions to the data context, since it expects expressions based on the LINQ to SQL entities.
发布评论
评论(5)
我遇到了和你一样的问题,我用 EF 修复了它:
实体框架知道如何构建正确的 sql 命令。 转换表达式要复杂得多,因为它被构建为不可变的,如果您做错了什么,可能会导致不良的运行时效果,并且至少在我的情况下,不需要它。
I had the same issue as you and i fixed it like this with EF:
Entity Framework knows how to build the correct sql command. Converting the expression is much more complicated, because it is built to be immutable and could cause undesired run time effects if you do something wrong, and, in my case at least, it is not needed.
对于
表达式
,最简单的方法是使用转换表达式:但请注意,不同的提供程序对此的支持会有所不同。 例如,EF 可能不喜欢它,即使 LINQ-to-SQL 喜欢它。
另一种选择是完全重建表达式树,使用反射来查找相应的成员。 复杂得多。
With
Expression
, the simplest way is with a conversion expression:Note however that this will be supported differently by different providers. EF might not like it, for example, even if LINQ-to-SQL does.
The other option is to rebuild the expression tree completely, using reflection to find the corresponding members. Much more complex.
我发现了另一种方法,其中还包括包装您的原始委托。
There is one other way I have found, that also includes wrapping your original delegate.
没有隐式的方法来进行翻译。 您必须将现有委托包装在 lambda 中,该 lambda 根据参数类型创建新类型:
其中
OtherTypeFromSomeType
从SomeType
创建OtherType
实例争论。There is no implicit way to do the translation. You have to wrap your existing delegate inside a lambda that creates a new type from the argument type:
Where
OtherTypeFromSomeType
creates theOtherType
instance from theSomeType
argument.就我而言,我也遇到了同样的不便,问题是我使用 AutoMapper 将信息从一个类传递到另一个类,在这种情况下,@Marc-Gravell 的解决方案不适用于 AutoMapper,但做了一些研究,我发现AutoMapper 可以将
Expression>
转换为Expression>
AutoMapper 配置如下 最后
,执行转换
此代码依赖于
AutoMapper
和AutoMapper.Extensions.ExpressionMapping
更多信息,可以查看 AutoMapper 并执行 表达式
In my case, I had the same inconvenience, the problem was that I was using AutoMapper to pass information from one class to another and in this case @Marc-Gravell's solution did not work for me with AutoMapper, but doing some research I found that AutoMapper can convert
Expression<Func<OrderLineDTO, bool>>
toExpression<Func<OrderLine, bool>>
The AutoMapper configuration would be the following
And finally, perform the conversion
This code depends on
AutoMapper
andAutoMapper.Extensions.ExpressionMapping
For more information, you can see the documentation of AutoMapper and to perform the expressions