Ошибка неверного числа аргументов при вызове метода

Ну, вы можете использовать Expression.AndAlso / OrElse и т. д. для объединения логических выражений, но проблема заключается в параметрах; вы работаете с тем же ParameterExpression в expr1 и expr2? Если это так, это проще:

var body = Expression.AndAlso(expr1.Body, expr2.Body);
var lambda = Expression.Lambda<Func<T,bool>>(body, expr1.Parameters[0]);

Это также хорошо работает, чтобы свести на нет одну операцию:

static Expression<Func<T, bool>> Not<T>(
    this Expression<Func<T, bool>> expr)
{
    return Expression.Lambda<Func<T, bool>>(
        Expression.Not(expr.Body), expr.Parameters[0]);
}

В противном случае, в зависимости от поставщика LINQ, вы можете скомбинируйте их с Invoke:

// OrElse is very similar...
static Expression<Func<T, bool>> AndAlso<T>(
    this Expression<Func<T, bool>> left,
    Expression<Func<T, bool>> right)
{
    var param = Expression.Parameter(typeof(T), "x");
    var body = Expression.AndAlso(
            Expression.Invoke(left, param),
            Expression.Invoke(right, param)
        );
    var lambda = Expression.Lambda<Func<T, bool>>(body, param);
    return lambda;
}

Где-то у меня есть код, который переписывает дерево выражений, заменяя узлы, чтобы удалить необходимость в Invoke, но он довольно длинный (и Я не могу вспомнить, где я его оставил ...)


Обобщенная версия, которая выбирает самый простой маршрут:

static Expression<Func<T, bool>> AndAlso<T>(
    this Expression<Func<T, bool>> expr1,
    Expression<Func<T, bool>> expr2)
{
    // need to detect whether they use the same
    // parameter instance; if not, they need fixing
    ParameterExpression param = expr1.Parameters[0];
    if (ReferenceEquals(param, expr2.Parameters[0]))
    {
        // simple version
        return Expression.Lambda<Func<T, bool>>(
            Expression.AndAlso(expr1.Body, expr2.Body), param);
    }
    // otherwise, keep expr1 "as is" and invoke expr2
    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(
            expr1.Body,
            Expression.Invoke(expr2, param)), param);
}

Начиная с .net 4.0. Существует класс ExpressionVistor, который позволяет создавать выражения, безопасные для EF.

    public static Expression<Func<T, bool>> AndAlso<T>(
        this Expression<Func<T, bool>> expr1,
        Expression<Func<T, bool>> expr2)
    {
        var parameter = Expression.Parameter(typeof (T));

        var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
        var left = leftVisitor.Visit(expr1.Body);

        var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
        var right = rightVisitor.Visit(expr2.Body);

        return Expression.Lambda<Func<T, bool>>(
            Expression.AndAlso(left, right), parameter);
    }



    private class ReplaceExpressionVisitor
        : ExpressionVisitor
    {
        private readonly Expression _oldValue;
        private readonly Expression _newValue;

        public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
        {
            _oldValue = oldValue;
            _newValue = newValue;
        }

        public override Expression Visit(Expression node)
        {
            if (node == _oldValue)
                return _newValue;
            return base.Visit(node);
        }
    }
23
задан iargin 20 September 2013 в 11:31
поделиться

2 ответа

Это будет хорошо.

    Object[] parameters ={new Object()}; // lets say this object array is null
    Class clas = Class.forName("AClass");
    Object anObject = clas.newInstance();

    Object[] param ={parameters};

    Method someMethod = clas.getDeclaredMethod("someMethod", parameters.getClass());
    someMethod.invoke(anObject, param);

Будьте осторожны со вторым параметром метода invoke. Это сам Object [], и тип аргумента вашего метода тоже Object [].

23
ответ дан biaobiaoqi 20 September 2013 в 11:31
поделиться

Метод Method.invoke принимает объект для получения вызова метода и массив аргументов метода. Поскольку ваш метод принимает один аргумент, указанный массив должен иметь размер один.

попробуйте создать новый массив размером 1:

someMethod.invoke(anObject, new Object[] {parameters});

Обратите внимание, что одно значение в этом массиве может быть нулевым. Это будет имитировать anObject.someMethod(null)

9
ответ дан orien 20 September 2013 в 11:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: