如何更改表达式树中的类型?

我有这样的方法:

private bool Method_1(Expression<Func> expression) { /* Some code that will call Method_2 */ } 

在这个方法中,我想将IPerson类型更改为另一种类型。 我想调用另一个看起来像这样的方法:

 private bool Method_2(Expression<Func> expression) { /* Some code */ } 

所以,在method_1我需要将IPerson更改为PersonData 。 我怎样才能做到这一点?

编辑:

当我调用时: Method_1(p => p.Id == 1)我想’保存’条件( p.Id == 1 )但是我想在另一种类型上执行这个条件,即IPerson 。 所以,我需要改变表达式或用IPerson创建一个新的表达式

编辑二:

对于那些感兴趣的人,这是(现在)我的解决方案:

 private class CustomExpressionVisitor : ExpressionVisitor { ParameterExpression _parameter; public CustomExpressionVisitor(ParameterExpression parameter) { _parameter = parameter; } protected override Expression VisitParameter(ParameterExpression node) { return _parameter; } protected override Expression VisitMember(MemberExpression node) { if (node.Member.MemberType == System.Reflection.MemberTypes.Property) { MemberExpression memberExpression = null; var memberName = node.Member.Name; var otherMember = typeof(T).GetProperty(memberName); memberExpression = Expression.Property(Visit(node.Expression), otherMember); return memberExpression; } else { return base.VisitMember(node); } } } 

这就是我使用它的方式:

 public virtual bool Exists(Expression<Func> expression) { var param = Expression.Parameter(typeof(I)); var result = new CustomExpressionVisitor(param).Visit(expression.Body); Expression<Func> lambda = Expression.Lambda<Func>(result, param); bool exists = _repository.Exists(lambda); return exists; } 

如果你使用.net 4(更新:注释中注释ExpressionVisitor是在版本4而不是4.5中添加),这很容易,它需要一些谷歌搜索旧框架:

有一些假设,但我认为它们对您的DTO和实体场景有效 – 访问的属性必须匹配。

 class PersonData { public bool Prop { get; set; } } interface IPerson { bool Prop { get; set; } } 

在.net 4中定义了ExpressionVisitor类,如果你使用旧的那个,那么你需要编写或找到它的实现:

 class Visitor : ExpressionVisitor { ParameterExpression _parameter; //there must be only one instance of parameter expression for each parameter //there is one so one passed here public Visitor(ParameterExpression parameter) { _parameter = parameter; } //this method replaces original parameter with given in constructor protected override Expression VisitParameter(ParameterExpression node) { return _parameter; } //this one is required because PersonData does not implement IPerson and it finds //property in PersonData with the same name as the one referenced in expression //and declared on IPerson protected override Expression VisitMember(MemberExpression node) { //only properties are allowed if you use fields then you need to extend // this method to handle them if (node.Member.MemberType != System.Reflection.MemberTypes.Property) throw new NotImplementedException(); //name of a member referenced in original expression in your //sample Id in mine Prop var memberName = node.Member.Name; //find property on type T (=PersonData) by name var otherMember = typeof(T).GetProperty(memberName); //visit left side of this expression p.Id this would be p var inner = Visit(node.Expression); return Expression.Property(inner, otherMember); } } 

概念certificate:

 class Program { static void Main() { //sample expression Expression> expression = x => x.Prop; //parameter that will be used in generated expression var param = Expression.Parameter(typeof(PersonData)); //visiting body of original expression that gives us body of the new expression var body = new Visitor(param).Visit(expression.Body); //generating lambda expression form body and parameter //notice that this is what you need to invoke the Method_2 Expression> lambda = Expression.Lambda>(body, param); //compilation and execution of generated method just to prove that it works var boolValue = lambda.Compile()(new PersonData()); } } 

请注意,这适用于简单表达式。 如果需要处理x.Prop.Prop1 < 3则需要进一步扩展。