将Expression<Func<in T, bool>>或Expression<Func<TBase,bool>>转换为Expression<Func<T,bool>>转换器

4
有没有简单的方法将HTML转换为纯文本?
Expression<Func<TBase,bool>> 

为了

Expression<Func<T,bool>>

T是从TBase继承而来的吗?

3个回答

3
只要 T 派生自 TBase,您就可以直接创建一个表达式,其中包含原始表达式的主体和参数。
Expression<Func<object, bool>> x = o => o != null;
Expression<Func<string, bool>> y = Expression.Lambda<Func<string, bool>>(x.Body, x.Parameters);

2
你可能需要手动进行转换。原因是你实际上是在将其转换为可能的子集。所有的 T 都是 TBase,但并非所有的 TBase 都是 T
好消息是,你可以使用 Expression.Invoke,并手动应用适当的强制转换/转换到 TBase(当然要捕获任何类型安全问题)。
编辑:我很抱歉误解了你想要走的方向。不过,我认为无论哪种情况,简单地转换表达式仍然是你最佳的路线。它能让你以任何方式处理转换。 Marc Gravell 在这里的回答 是我见过的最紧凑和清晰的做法。

为什么要手动转换?我将E<F<TBase,bool>>转换为E<F<T,bool>>,这样在使用TBase的每个地方都可以使用T。 - Vladimir
这是我的错。我误解了您想要转换的方向。我的原始答案已更新,提供了一个比我能想到的更好的答案链接。 - drharris

0
为了实现这个,我编写了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();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接