Лямбда-выражение Func с более чем 16 параметрами - PullRequest
1 голос
/ 13 декабря 2011

Мне нужно написать фильтрующее лямбда-выражение, используемое в LinqToSQL, для которого требуется больше, чем количество параметров, предоставляемых стандартным System.Func (в этом случае максимальное число - 16).

Expression<Func<BusinessDTO,
                                string,
                                int,
                                int,
                                int,
                                DateTime,
                                DateTime,
                                DateTime,
                                DateTime,
                                DateTime,
                                DateTime,
                                DateTime,
                                DateTime,
                                int,
                                int,
                                int,
                                int,//-> Max number exceeded 
                                bool>> fnFilter = (business,
                                                        Name,
                                                        Redeemed,
                                                        Permanent,
                                                        ApprovedByUser,
                                                        BeginApprovalDate,
                                                        EndApprovalDate,
                                                        BeginExpiryDate,
                                                        EndExpiryDate,
                                                        BeginEntryDate,
                                                        EndEntryDate,
                                                        BeginChangeDate,
                                                        EndChangeDate,
                                                        WorkFlowCode,
                                                        CreatedByUser,
                                                        UpdatedByUser) => ...

Как я могу добиться этого?

Вот использование:

filterExpression = Expression.Invoke(fnFilter, businessParam,
                                   Expression.Constant(name),
                                   Expression.Constant(redeemed),
                                   Expression.Constant(permanent),
                                   Expression.Constant(approvedByUser),
                                   Expression.Constant(filter.BeginApprovalDate),
                                   Expression.Constant(filter.EndApprovalDate),
                                   Expression.Constant(filter.BeginExpiryDate),
                                   Expression.Constant(filter.EndExpiryDate),
                                   Expression.Constant(filter.BeginEntryDate),
                                   Expression.Constant(filter.EndEntryDate),
                                   Expression.Constant(filter.BeginChangeDate),
                                   Expression.Constant(filter.EndChangeDate),
                                   Expression.Constant(workflowCode),
                                   Expression.Constant(createdByUser),
                                   Expression.Constant(updatedByUser));

var resultExpression = Expression.Equal(filterExpression, Expression.Constant(true));
            var predicate = Expression.Lambda<Func<BusinessDTO, bool>>(resultExpression, businessParam);

repository.FindAll(predicate);

1 Ответ

1 голос
/ 13 декабря 2011

Наш продукт столкнулся с этим ограничением еще в .NET 3.5 дня, когда ограничение было 4. Мы закончили сгруппировать дополнительные параметры в один объект, для которого мы создали чудовищный универсальный тип с 32 параметрами типа:

class FilterParams<T1,T2,T3,T4,/*..*/,T32> {
    public T1 t1Val {get;set;}
    public T2 t1Val {get;set;}
    public T3 t1Val {get;set;}
    // ...
}

Expression<Func<BusinessDTO,FilterParams<
                    string,
                    int,
                    int,
                    int,
                    DateTime,
                    DateTime,
                    DateTime,
                    DateTime,
                    DateTime,
                    DateTime,
                    DateTime,
                    DateTime,
                    int,
                    int,
                    int,
                    int,//-> Max number is not exceeded :)
                    bool,object,object,/* pad to 32 ...*/>> fnFilter = (business,
                         filterParams) => business.Name.Equals(filterParams.t0val) && ...

var fp = new FilterParams</*ugly type parameter list*/>(
    t0val = name,
    t1val = redeemed,
    t2val = permanent,
    // ...and so on
);

filterExpression = Expression.Invoke(fnFilter, businessParam, Expression.Constant(fp));

// ...the rest is the same as in your post

Это сработало довольно хорошо для нас. В итоге мы расширили его до 64 и создали 64 различных класса, чтобы избежать параметров типа заполнения с object, как показано выше. Конечно, мы написали небольшой скрипт для генерации этих 64 общих классов.

...