问题描述
我之前使用过基于 lamdas 的 C# 表达式,但我没有手工编写它们的经验.给定一个 Expression
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.
在这种情况下 SomeType 和 OtherType 具有相同的字段,但它们不相关(没有继承,也不是基于公共接口).
In this case SomeType and OtherType have the same fields, but they are not related (no inheritance and not based on a common interface).
背景:我有一个基于 LINQ to SQL 的存储库实现.我将 LINQ to SQL 实体投影到我的模型实体,以将我的模型保存在 POCO 中.我想将表达式传递给存储库(作为规范的一种形式),但它们应该基于模型实体.但我无法将这些表达式传递给数据上下文,因为它需要基于 LINQ to SQL 实体的表达式.
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.
推荐答案
用Expression,最简单的方法就是用一个转换表达式:
With Expression, the simplest way is with a conversion expression:
class Foo { public int Value { get; set; } } class Bar { public int Value { get; set; } } static class Program { static void Main() { Expression<Func<Foo, bool>> predicate = x => x.Value % 2 == 0; Expression<Func<Bar, Foo>> convert = bar => new Foo { Value = bar.Value }; var param = Expression.Parameter(typeof(Bar), "bar"); var body = Expression.Invoke(predicate, Expression.Invoke(convert, param)); var lambda = Expression.Lambda<Func<Bar, bool>>(body, param); // test with LINQ-to-Objects for simplicity var func = lambda.Compile(); bool withOdd = func(new Bar { Value = 7 }), withEven = func(new Bar { Value = 12 }); } }
但是请注意,不同的提供商会对此提供不同的支持.例如,EF 可能不喜欢它,即使 LINQ-to-SQL 喜欢.
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.