C# 如何将 Expression<Func<SomeType>> 转换为 Expression<Func<OtherType>>
Posted
技术标签:
【中文标题】C# 如何将 Expression<Func<SomeType>> 转换为 Expression<Func<OtherType>>【英文标题】:C# How to convert an Expression<Func<SomeType>> to an Expression<Func<OtherType>> 【发布时间】:2010-10-13 20:09:48 【问题描述】:我之前使用过基于 lamdas 的 C# 表达式,但我没有手工编写它们的经验。给定一个Expression<Func<SomeType, bool>> originalPredicate
,我想创建一个Expression<Func<OtherType, bool>> translatedPredicate
。
在这种情况下 SomeType 和 OtherType 具有相同的字段,但它们不相关(没有继承并且不基于公共接口)。
背景:我有一个基于 LINQ to SQL 的存储库实现。我将 LINQ to SQL 实体投影到我的模型实体中,以将我的模型保存在 POCO 中。我想将表达式传递给存储库(作为规范的一种形式),但它们应该基于模型实体。但我无法将这些表达式传递给数据上下文,因为它需要基于 LINQ to SQL 实体的表达式。
【问题讨论】:
回复在这个话题:***.com/questions/4601844/… 【参考方案1】:使用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 喜欢。
另一种选择是完全重建表达式树,使用反射找到相应的成员。复杂得多。
【讨论】:
我希望 L2EF 喜欢这个,因为我将表达式从接口转换为具体类,并将结果作为 IQueryable我发现了另一种方法,也包括包装您的原始委托。
Func<T, object> ExpressionConversion<U>(Expression<Func<T, U>> expression)
Expression<Func<T, object>> g = obj => expression.Compile().Invoke(obj);
return g.Compile();
【讨论】:
【参考方案3】:没有隐含的方式来进行翻译。您必须将现有委托包装在 lambda 中,该 lambda 从参数类型创建新类型:
var translatedPredicate = x => originalPredicate(OtherTypeFromSomeType(x))
OtherTypeFromSomeType
从SomeType
参数创建OtherType
实例。
【讨论】:
问题是关于表达式,而不是代表。您不能使用这种方法来调用子表达式;它更复杂。 糟糕,没有仔细阅读。无论如何,技术基本相同,表达式只是需要更多的工作(即使从技术上讲,我的代码在第一次编译originalPredicate
并使用 Expression<…>
而不是 var
后仍然可以工作;-))。【参考方案4】:
我和你有同样的问题,我用 EF 解决了这个问题:
var viewModeValue = dbContext.Model.Select(m => new ViewModelField = m.Field).Where(predicate) //predicate is an Expression<Func<ViewModel, bool>>
Entity Framework 知道如何构建正确的 sql 命令。转换表达式要复杂得多,因为它是不可变的,如果你做错了可能会导致不希望的运行时效果,至少在我的情况下,它是不需要的。
【讨论】:
以上是关于C# 如何将 Expression<Func<SomeType>> 转换为 Expression<Func<OtherType>>的主要内容,如果未能解决你的问题,请参考以下文章
c# linq语句的Expression<Func<TEntity,bool>>怎么传进参数
如何动态创建 Expression<Func<MyClass, bool>> 谓词?
如何从 Expression<Func<MyClass, string>> 动态创建 Expression<Func<MyClass, bool>> 谓