C# 如何表达<;Func<;T1,bool>&燃气轮机;表达<;Func<;T2,bool>>;?

C# 如何表达<;Func<;T1,bool>&燃气轮机;表达<;Func<;T2,bool>>;?,c#,C#,如何将表达式转换为表达式? 注意T1和T2都有相同的接口。这是一个示例解决方案,不要在实际代码中使用它 如果childExpression使用的不是Base属性,则此操作将中断。如果您有许多参数(演示访问者是以尽可能简单的方式实现的),则会出现这种情况。在很多情况下,这可能会中断,它只能用于解释目的 现在,解释 可以通过访问表达式并将参数替换为新参数来完成此任务: class Base { public string Name { get; set; } } class Child :

如何将
表达式
转换为
表达式
注意T1和T2都有相同的接口。

这是一个示例解决方案,不要在实际代码中使用它 如果
childExpression
使用的不是
Base
属性,则此操作将中断。如果您有许多参数(演示访问者是以尽可能简单的方式实现的),则会出现这种情况。在很多情况下,这可能会中断,它只能用于解释目的

现在,解释 可以通过访问表达式并将参数替换为新参数来完成此任务:

class Base
{
    public string Name { get; set; }
}

class Child : Base { }
假设您有一个用于
子对象的
表达式,该表达式只使用
。Name

var childExpression = (Expression<Func<Child, bool>>)(e => e.Name == "works!");
取出旧尸体:

var newBody = childExpression.Body;
好吧,这有一个问题:旧的body正在使用内部旧参数的引用,我们需要用新的参数替换它

class ParameterReplacer : ExpressionVisitor
{
    private ParameterExpression _newParameter;

    public ParameterReplacer(ParameterExpression newParameter)
    {
        _newParameter = newParameter;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        return _newParameter; // forget about the old one, return the new
    }
}
这样我们就可以通过适当的参考来获得我们的身体:

var body = new ParameterReplacer(newParameter).Visit(childExpression.Body);
并将结果组合成一个完美键入的
表达式


你不能。演员阵容将永远无效,因为没有任何
表达式
将实际成为
表达式
实例。您需要访问该表达式并用基本接口替换参数,或者创建一个使用
Convert
的新表达式,前提是您可以从
T1
转换为
T2
。如果T1和T2具有相同的接口,然后为他们创建一个接口(比如
interface it1和2
),让他们显式地实现该接口,并使用
Expression>
盲目返回
\u newParameter
,而不检查
节点
似乎很危险。但更重要的是,我没有从这个问题中得到这样的印象,即一种类型是另一种类型的子类,在这种情况下,这种方法将不起作用。@hvd是的,它确实是,这是一个快速和最小的工作example@IvanSanz-Carasa仅仅因为您能够创建一个工作示例,并不意味着您可以提供一个解决方案,该解决方案可以在所有其他情况下中断,除了一个示例。@hvd注意,即使目标类型是原始类型的基类型,它仍然不安全。原始表达式可能使用了在
Child
中定义的成员,但正如您所注意到的,它们可能不在同一继承链中。这正是OP描述的情况,请不要这么粗鲁。如果您有更好的方法向他解释表达式参数替换的概念,我很高兴看到@Servy
var body = new ParameterReplacer(newParameter).Visit(childExpression.Body);
var expressionForBase = Expression.Lambda<Func<Base, bool>>(body, newParameter);
var predicate = expressionForBase.Compile().Invoke(new Base
{
    Name = "works!"
}); // true!