Условная фильтрация IQueryable <T>по выражению и второму объекту - PullRequest
1 голос
/ 04 мая 2019

Я не уверен, что заголовок удовлетворяет моему вопросу ...

Но я пытаюсь создать собственный метод расширения в IQueryable, где мое выражение выбирает объект типа AgentEntity, а второй параметр того же типа, но используется для условной фильтрации.

Вот мой код, который не работает, но предлагает то, что я хотел бы сделать.

public static IQueryable<T> Where<T>(this IQueryable<T> profiles, Func<AgentEntity, AgentEntity> agentSelector, AgentEntity agent)
{
    if (string.IsNullOrEmpty(agent.Mbox))
    {
        return profiles.Where(agentSelector.Mbox == agent.Mbox);
    }

    if (string.IsNullOrEmpty(agent.Mbox_SHA1SUM))
    {
        return profiles.Where(agentSelector.Mbox_SHA1SUM == agent.Mbox_SHA1SUM);
    }

    if (string.IsNullOrEmpty(agent.OpenId))
    {
        return profiles.Where(agentSelector.OpenId == agent.OpenId);
    }

    if (string.IsNullOrEmpty(agent.Account.HomePage))
    {
        return profiles.Where(agentSelector.Account.HomePage == agent.Account.HomePage && agentSelector.Account.Name == agent.Account.Name);
    }

    return profiles;
}

Использование

AgentEntity agent = new AgentEntity(){
  Mbox = "mailto:lorem@example.com"
}
_dbContext.OtherEntity.Where(x=> x.Agent, agent);
_dbContext.ThirdEntity.Where(x=> x.Object.Agent, agent);

Как преобразовать agentSelector в следующее выражение x=> x.Mbox == agent.Mbox или одно из других условий, чтобы использовать его в предложении Where для фильтрации профилей.

Предложение profiles.Where ожидает Expression<Func<T, bool>> predicate

Спасибо!

1 Ответ

1 голос
/ 06 мая 2019

IQueryable может быть отфильтровано с использованием метода Where. Этот метод также возвращает IQueryable, поэтому, если вы хотите (и я часто это делаю), вы можете объединить их в цепочку для многократной фильтрации - я считаю, что это приводит к более читабельному коду, а также вы можете ветвить код между этими фильтрами (чтобы добавить условия того, фильтруете ли вы или нет). Это может выглядеть примерно так (извинения, непроверенный код, но приветствую любые изменения, если я сделаю некоторые опечатки!):

IQueryable<Foo> foos = _dbContext.Foos;
foos = foos.Where(f => f.Bar == myBar);

if(!string.IsNullOrNothing(myBaz)){
    foos = foos.Where(f => f.Baz == myBaz)
}

Таким образом, в этом коде набор Foo объектов всегда фильтруется, когда их свойство Bar равно myBar, но вторая фильтрация применяется только тогда, когда myBar равно , а не null и не ничего (обратите внимание на то, что ! делает это не так, что является одной из точек dotNet, и оба считают, что в вашем исходном коде отсутствует)

Теперь позвольте мне применить это к методу расширения, который вы пытаетесь создать. Сложность заключается в том, что существуют различные сопоставления, которые можно получить из OtherEntity или ThirdEntity и AgentEntity, и мы хотим использовать Func<T, AgentEntity> для определения этого сопоставления (обратите внимание, что мы сопоставляем из универсального типа 'T')

public static IQueryable<T> Where<T>(this IQueryable<T> profiles, Func<T, AgentEntity> mapping, AgentEntity agent)
{
    if (!string.IsNullOrEmpty(agent.MBox))
    {
        profiles = profiles.Where(p => mapping(p).MBox == agent.MBox);
    }

    return profiles;
}

Обратите внимание, что мы используем переданную функцию отображения для преобразования каждого профиля в агента, который мы используем для фильтра. Он вызывается так же, как в вашем первоначальном вопросе:

_dbContext.OtherEntity.Where(x=> x.Agent, agent);

Также обратите внимание, что я не возвращаюсь до конца функции - это может или не может быть тем, что вы на самом деле хотите - вы можете захотеть вернуться, как только найдете один критерий, по которому вы можете фильтровать!

Надеюсь, что вы на правильном пути!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...