转换 Lambda 表达式参数类型
本文关键字:类型 参数 表达式 Lambda 转换 | 更新日期: 2023-09-27 18:34:12
如果我有以下类...
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")));
。但这似乎行不通。
进行此转换的最佳方法是什么。 从我记得的工作来看,表达式树的内部部分(在本例中为成员表达式)似乎绑定到特定类型。 我是否需要解析整个表达式树才能进行转换? 我缺少一些简单的东西吗?
我不知道
你想做什么。我只是理解您正在尝试使您的 lambda 表达式与 Source
和 Destination
兼容,而无需为每个表达式创建两个 lambda 表达式。
根据我的理解。
首先创建一个这样的接口:
public interface IName
{
string Name { get; set; }
}
然后Source
并Destination
实现新接口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
的所有类兼容。
我缺少一些简单的东西吗?
如果事实处理所有可能的情况并不简单。仅支持谓词参数的属性/字段访问器的简化函数可能是这样的
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);