Необходимо объединить && неопределенное количество Func

Я пытаюсь найти хороший способ кумулятивно применить до 5 Func к одному и тому же IEnumerable. Вот что я придумал:

private Func<SurveyUserView,bool> _getFilterLambda(IDictionary<string, string> filters)
{
    Func<SurveyUserView, bool> invokeList = delegate(SurveyUserView surveyUserView)
    { 
        return surveyUserView.deleted != "deleted"; 
    };

    if (filters.ContainsKey("RegionFilter"))
    {
        invokeList += delegate(SurveyUserView surveyUserView)
        {
            return surveyUserView.Region == filters["RegionFilter"];
        };
    }

    if (filters.ContainsKey("LanguageFilter"))
    {
        invokeList += delegate(SurveyUserView surveyUserView)
        {
            return surveyUserView.Locale == filters["LanguageFilter"];
        };
    }

    if (filters.ContainsKey("StatusFilter"))
    {
        invokeList += delegate(SurveyUserView surveyUserView)
        { 
            return surveyUserView.Status == filters["StatusFilter"]; 
        };
    }

    if (filters.ContainsKey("DepartmentFilter"))
    {
        invokeList += delegate(SurveyUserView surveyUserView)
        {
            return surveyUserView.department == filters["DepartmentFilter"];
        };
    }

    return invokeList;
}

Я думал, что они будут применяться кумулятивно, однако из результатов я вижу, что на самом деле применяется только последний (DepartmentFilter)

Существует 2^4 возможных комбинации, поэтому грубая сила if/elses не будет работать (я хочу, чтобы И использовал конкретную лямбду только тогда, когда соответствующий ключ присутствует в словаре.)

РЕДАКТИРОВАТЬ: Вот решение, которое я принял, но оно вызывает исключение StackOverflowException при его оценке. Кто-нибудь видит, почему?

private Func<SurveyUserView,bool> _getFilterLambda(IDictionary<string, string> filters )
    {

        Func<SurveyUserView, bool> resultFilter = (suv) => suv.deleted != "deleted";                                                        

        if (filters.ContainsKey("RegionFilter"))
        {
            Func<SurveyUserView, bool> newFilter =
                (suv) => resultFilter(suv) && suv.Region == filters["RegionFilter"];
            resultFilter = newFilter;
        }

        if (filters.ContainsKey("LanguageFilter"))
        {
            Func<SurveyUserView, bool> newFilter =
                 (suv) => resultFilter(suv) && suv.Locale == filters["LanguageFilter"];
            resultFilter = newFilter;
        }

        if (filters.ContainsKey("StatusFilter"))
        {
            Func<SurveyUserView, bool> newFilter =
                (suv) => resultFilter(suv) && suv.Status == filters["StatusFilter"];
            resultFilter = newFilter;
        }

        if (filters.ContainsKey("DepartmentFilter"))
        {
            Func<SurveyUserView, bool> newFilter =
                (suv) => resultFilter(suv) && suv.department == filters["DepartmentFilter"];
            resultFilter = newFilter;
        }

        return resultFilter;
    }

РЕДАКТИРОВАТЬ: Вот очень хорошее объяснение того, почему это привело к исключению StackOverflowException, от друга и наставника Криса Флатера:

Важным моментом для понимания того, почему возникает бесконечная рекурсия, является понимание того, когда разрешаются символы в лямбда-выражении (т.е. во время выполнения, а не во время выполнения). определение).

Возьмем этот упрощенный пример:

Func<int, int> demo = (x) => x * 2;
Func<int, int> demo2 = (y) => demo(y) + 1;
demo = demo2;
int count = demo(1);

Если бы это было разрешено статически при определении, это будет работать и будет таким же, как:

Func<int, int> demo2 = (y) => (y * 2) + 1;
Int count = demo2(1);

Но на самом деле он не пытается выяснить, что делает демо, встроенное в demo2, до времени выполнения – в это время demo2 был переопределен как demo. По сути, теперь код выглядит следующим образом:

Func<int, int> demo2 = (y) => demo2(y) + 1;
Int count = demo2(1);
6
задан Trey Carroll 5 June 2012 в 21:10
поделиться