C# 通过输入参数来减少表达式

C# 通过输入参数来减少表达式,c#,.net,lambda,delegates,C#,.net,Lambda,Delegates,如果我有一个函数委托的表达式,它接受许多参数,如下所示: Expression<Func<int, int, int, bool>> test = (num1, num2, num3) => num1 + num2 == num3; 编辑: 还需要解决复杂类型,例如: Expression<Func<Thing, int, int>> test = (thing, num2) => thing.AnIntProp + num2

如果我有一个函数委托的表达式,它接受许多参数,如下所示:

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

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

    Expression<Func<Thing, int, int>> test = (thing, num2) => thing.AnIntProp + num2;
expressiontest=(thing,num2)=>thing.aninttop+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);
    }
}
这将只解析字段或属性。下一步可能是添加对方法的支持(但由于它们本身有参数,所以这将需要更多的工作…)


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

可能重复的虽然我投票的是dup,但这个问题实际上可能不同。也许您正在寻找表达式访问者的用法,以值替换参数?(大致的)不完全是。我想和表达式一起工作。我认为它更接近或我能够成功地使用它。但是,在比较表达式中解析为非null值时,我遇到了可为null类型的问题。在解析过程中,常量表达式推断数据类型,例如,
DateTime
,而不是
DateTime?
。为了解决这个问题,我显式地传递类型:
returnexpression.Constant(newVal,m.type)。这使它保持原来的类型。
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);
    }
}
Expression<Func<Thing, int, bool>> test = (thing, num) => thing.AnIntProperty == num;
      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);
    }