首页 文章

转换Lambda表达式参数类型

提问于
浏览
2

如果我有以下课程......

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;

...我最终得到的是一个lambda表达式,其中包含 Source 类型的单个参数( e ) . 我想要做的是将此表达式转换为 Destination 类型的参数 .

我尝试过像......

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

......但这似乎不起作用 .

进行此转换的最佳方法是什么 . 从我记得的工作开始,似乎表达式树的内部部分(在本例中是成员表达式)绑定到特定类型 . 我是否需要解析整个表达式树才能进行转换?我有什么简单的遗失吗?

2 回答

  • 0

    我不知道你到底想要做什么 . 我只是明白你正试图使你的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";
    

    这个lambda表达式与所有推动 IName 接口的类兼容 .

  • 1

    我有什么简单的遗失吗?

    如果事实处理所有可能的情况并不简单 . 仅支持谓词参数的属性/字段访问器的简化函数可以是这样的

    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);
    

相关问题