转换Lambda表达式参数类型

问题描述:

如果我有以下类...转换Lambda表达式参数类型

public class Source 
{ 
    public string Name 
    { 
    get; 

    set; 
    } 
} 

public class Destination 
{ 
    public string Name 
    { 
    get; 

    set; 
    } 
} 

...我有下面的代码来创建一个表达式....

Expression<Func<Source, bool>> expression = e => e.Name == "Test; 

.. 。我最终得到的是带有Source类型的单个参数(e)的lambda表达式。我正在尝试将此表达式转换为Destination类型的参数。

我已经试过类似...

Expression<Func<Destination, bool>> expression2 = Expression.Lambda<Func<Destination, bool>>(expression.Body, Expression.Parameter(typeof(Destination), "e"))); 

...但是这似乎并没有工作。

什么是最好的这种转换方式。看起来,从我记得的工作中,表达式树的内部部分(在这种情况下是成员表达式)被绑定到特定的类型。我是否需要解析整个表达式树才能进行转换?有没有简单的我失踪?

+3

什么是你想做什么目的? – CodeNotFound

+0

你的问题不清楚。转换意味着什么?你的意思是转换或者你正在尝试改变构建表达式的代码? – vendettamit

我不确切地知道你在做什么。我只是明白,你正试图让你的lambda表达式与SourceDestination兼容,而不必为每个表达式创建两个lambda表达式。

基于我的理解。

首先创建这样一个接口:

public interface IName 
{ 
    string Name { get; set; } 
} 

然后让SourceDestination实施新界面IName如下:

public class Source : IName 
{ 
    public string Name { get; set; } 
} 

public class Destination : IName 
{ 
    public string Name { get; set; } 
} 

那么你的lambda表达式只会是这样的:

Expression<Func<IName, bool>> expression = e => e.Name == "Test"; 

thi s的lambda表达式兼容所有推动接口的类。

+0

我同意这通常是最好的方法,但如果Source或Destination是第三方软件呢? –

+0

只需将其包装到实现该界面的另一个类中。 – CodeNotFound

有没有简单的我失踪?

如果事实处理所有可能的情况并不简单。支持谓词参数的唯一属性/字段的访问器的简化功能也能像这样

public static class ExpressionUtils 
{ 
    public static Expression<Func<TTarget, bool>> Convert<TSource, TTarget>(Expression<Func<TSource, bool>> source) 
    { 
     var parameter = Expression.Parameter(typeof(TTarget), source.Parameters[0].Name); 
     var body = new ParameterConverter { source = source.Parameters[0], target = parameter }.Visit(source.Body); 
     return Expression.Lambda<Func<TTarget, bool>>(body, parameter); 
    } 

    class ParameterConverter : ExpressionVisitor 
    { 
     public ParameterExpression source; 
     public ParameterExpression target; 
     protected override Expression VisitParameter(ParameterExpression node) 
     { 
      return node == source ? target : base.VisitParameter(node); 
     } 
     protected override Expression VisitMember(MemberExpression node) 
     { 
      return node.Expression == source ? Expression.PropertyOrField(target, node.Member.Name) : base.VisitMember(node); 
     } 
    } 
} 

而且与样品的用法是:

Expression<Func<Source, bool>> source = e => e.Name == "Test; 
var target = ExpressionUtils.Convert<Source, Destination>(source);