为了账号安全,请及时绑定邮箱和手机立即绑定

将谓词的表达式树突变为目标另一种类型

将谓词的表达式树突变为目标另一种类型

C#
智慧大石 2019-11-28 14:11:49
介绍在我当前正在处理的应用程序中,每种业务对象都有两种:“ ActiveRecord”类型和“ DataContract”类型。因此,例如,将有:namespace ActiveRecord {    class Widget {        public int Id { get; set; }    }}namespace DataContract {    class Widget {        public int Id { get; set; }    }}数据库访问层负责在族之间进行转换:您可以告诉它更新a DataContract.Widget,它将神奇地创建一个ActiveRecord.Widget具有相同属性值的an 并将其保存。尝试重构此数据库访问层时出现了问题。问题我想将以下方法添加到数据库访问层:// Widget is DataContract.Widgetinterface IDbAccessLayer {    IEnumerable<Widget> GetMany(Expression<Func<Widget, bool>> predicate);}上面是带有自定义谓词的简单的通用“ get”方法。唯一感兴趣的一点是,我传递的是表达式树而不是lambda,因为在内部IDbAccessLayer我正在查询IQueryable<ActiveRecord.Widget>; 为了有效地做到这一点(想想LINQ to SQL),我需要传递一个表达式树,这样该方法就可以做到这一点。障碍:需要将参数从神奇地转换Expression<Func<DataContract.Widget, bool>>为Expression<Func<ActiveRecord.Widget, bool>>。尝试的解决方案我想在里面做的GetMany是:IEnumerable<DataContract.Widget> GetMany(    Expression<Func<DataContract.Widget, bool>> predicate){    var lambda = Expression.Lambda<Func<ActiveRecord.Widget, bool>>(        predicate.Body,        predicate.Parameters);    // use lambda to query ActiveRecord.Widget and return some value}这将不起作用,因为在典型情况下,例如:predicate == w => w.Id == 0;...表达式树包含一个MemberAccessExpression实例,该实例的属性类型MemberInfo为describe DataContract.Widget.Id。ParameterExpression在表达式树及其参数集合(predicate.Parameters)中也有实例描述DataContract.Widget; 所有这些都会导致错误,因为可查询主体不包含该类型的小部件,而是ActiveRecord.Widget。搜索了一下后,我发现System.Linq.Expressions.ExpressionVisitor(其来源可以发现这里的如何做的情况下),它提供了一个方便的方式来修改表达式树。在.NET 4中,该类是开箱即用的。有了这个,我实现了一个访客。这个简单的访问者只需要更改成员访问和参数表达式中的类型,但这足以使用谓词w => w.Id == 0。结果好消息是,lambda它的构造很好。坏消息是它不起作用。当我尝试使用它时,它就爆炸了,异常消息真的根本没有帮助。我检查了我的代码产生的lambda和具有相同表达式的硬编码lambda。他们看起来完全一样。我在调试器中花了几个小时试图找到一些区别,但是我做不到。当谓词为时w => w.Id == 0,lambda看起来完全像referenceLambda。但是后者适用于例如IQueryable<T>.Where,而前者则不适用;我已经在调试器的即时窗口中尝试过此操作。我还应该提到,当谓词为时w => true,一切正常。因此,我假设我没有在访问者中做足够的工作,但是我找不到更多的线索可循。最终解决方案在考虑了问题的正确答案之后(以下两个);一个简短的问题,一个带有代码的问题得以解决;我将代码和一些重要说明放在一个单独的答案中,以防止这个漫长的问题变得更长。感谢大家的回答和评论!
查看完整描述

3 回答

  • 3 回答
  • 0 关注
  • 365 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信