c# - 通过输入参数减少表达式

标签 c# .net lambda delegates

如果我有一个带有多个参数的函数委托(delegate)表达式,如下所示:

Expression<Func<int, int, int, bool>> test = (num1, num2, num3) => num1 + num2 == num3;

有没有办法/如何替换其中一个值(例如 5 代替 num1)并获得等效表达式:

Expression<Func<int, int, bool>> test = (num2, num3) => 5 + num2 == num3;

编辑:

还需要解析复杂类型,例如:

    Expression<Func<Thing, int, int>> test = (thing, num2) => thing.AnIntProp + num2;

最佳答案

我的回答是使用一个表达式 visitor。 (感谢@Alexei-levenkov 指出)。

我的特定情况的答案与我在问题中使用的简化示例略有不同。但是,为了完整起见,我是这样做的:

public class ResolveParameterVisitor : ExpressionVisitor
{
    private readonly ParameterExpression _param;
    private readonly object _value;

    public ResolveParameterVisitor(ParameterExpression param, object value)
    {
        _param = param;
        _value = value;
    }

    public Expression ResolveLocalValues(Expression exp)
    {
        return Visit(exp);
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        if (node.Type == _param.Type && node.Name == _param.Name
            && node.Type.IsSimpleType())
        {
            return Expression.Constant(_value);
        }

            return base.VisitParameter(node);
    }

    protected override Expression VisitLambda<T>(Expression<T> node)
    {
        var parameters = node.Parameters.Where(p => p.Name != _param.Name && p.Type != _param.Type).ToList();
        return Expression.Lambda(Visit(node.Body), parameters);
    }
}

请注意,IsSimpleType 是我从 this gist 借用的扩展乔诺桑康威。

在我的情况下,我想替换对复杂类型的使用。例如:

Expression<Func<Thing, int, bool>> test = (thing, num) => thing.AnIntProperty == num;

所以我重写了 VisitMember 方法。这仍在进行中,但看起来像这样:

      protected override Expression VisitMember(MemberExpression m)
    {
        if (m.Expression != null
            && m.Expression.NodeType == ExpressionType.Parameter
            && m.Expression.Type == _param.Type && ((ParameterExpression)m.Expression).Name == _param.Name)
        {
            object newVal;
            if (m.Member is FieldInfo)
                newVal = ((FieldInfo)m.Member).GetValue(_value);
            else if (m.Member is PropertyInfo)
                newVal = ((PropertyInfo)m.Member).GetValue(_value, null);
            else
                newVal = null;
            return Expression.Constant(newVal);
        }

        return base.VisitMember(m);
    }

这只会解析一个字段或属性。下一步可能是添加对方法的支持(但由于它们本身有参数,因此需要更多工作...)

编辑:上述成员访问者解决方案也不支持将对象本身传递到方法调用中。例如(x, thing) => x.DoSomething(thing) 因此也需要进行修改才能做到这一点。

关于c# - 通过输入参数减少表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17960103/

相关文章:

c# - 使用哪种测试方法?

c# - 我如何验证日期不是 .net c# 中的 future 日期

c# - Entity Framework 问题 - 将 "1"附加到我的表名?

.net - ODP.NET程序编译

c# - 如何组织此代码以在显示窗口后加载报告?

c# - 在 .NET 中以编程方式配置网络适配器的最佳方式

c# - 为什么没有 ICloneable<T>?

vb.net - 直接使用函数和作为 lambda 表达式使用函数

c# - 我对 LINQ 缺乏了解

python - 对 Python 函数的代码(包括 lambda)进行哈希处理