繁体   English   中英

表达<func<in t, bool> &gt; 或表达式<func<tbase,bool> &gt; 到表达式<func<t,bool> &gt; 转换器</func<t,bool></func<tbase,bool></func<in>

[英]Expression<Func<in T, bool>> or Expression<Func<TBase,bool>> to Expression<Func<T,bool>> Converter

有没有简单的转换方法

Expression<Func<TBase,bool>> 

Expression<Func<T,bool>>

T 是从 TBase 继承的?

只要 T 从 TBase 派生,您就可以使用原始表达式的主体和参数直接创建所需类型的表达式。

Expression<Func<object, bool>> x = o => o != null;
Expression<Func<string, bool>> y = Expression.Lambda<Func<string, bool>>(x.Body, x.Parameters);

您可能需要手动转换。 这样做的原因是您正在有效地转换为它可能的子集。 所有T都是TBase ,但并非所有TBase都是T

好消息是您可能可以使用Expression.Invoke来完成,并手动将适当的强制转换/转换应用到TBase (当然会发现任何类型安全问题)。

编辑:我很抱歉误解了你想要 go 的方向。我认为简单地转换表达式仍然是你最好的方法。 它使您能够随心所欲地处理转换。 Marc Gravell 的回答是我见过的最简洁明了的方法。

为此,我编写了 ExpressionVisitor,重载了 VisitLambda 和 VisitParameter

这里是:

public class ConverterExpressionVisitor<TDest> : ExpressionVisitor
{
    protected override Expression VisitLambda<T>(Expression<T> node)
    {
        var readOnlyCollection = node.Parameters.Select(a => Expression.Parameter(typeof(TDest), a.Name));
        return Expression.Lambda(node.Body, node.Name, readOnlyCollection);
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        return Expression.Parameter(typeof(TDest), node.Name);
    }
}

public class A { public string S { get; set; } }
public class B : A { }

static void Main(string[] args)
{
    Expression<Func<A, bool>> ExpForA = a => a.S.StartsWith("Foo");
    Console.WriteLine(ExpForA); // a => a.S.StartsWith("Foo");

    var converter = new ConverterExpressionVisitor<B>();
    Expression<Func<B, bool>> ExpForB = (Expression<Func<B, bool>>)converter.Visit(ExpForA);
    Console.WriteLine(ExpForB); // a => a.S.StartsWith("Foo"); - same as for A but for B
    Console.ReadLine();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM