PredicateBuilder / LINQ Инкапсуляция предикатов, DI - PullRequest
2 голосов
/ 27 января 2012

Я начал замечать, что мой код построения предиката выглядит примерно так. Это знак для рефакторинга. Давайте посмотрим на код.

    var predicate = PredicateBuilder.False<ArticleLikeInfo>();

    // Under the covers it will get Guid from a cookie (one way to track a user)
    Guid? key = _userKeyService.GetKey();
    if (key.HasValue)
    {
        predicate = predicate.OrElse(x => x.UserKey == key.Value);
    }

    String ip = Request.UserHostAddress;
    if (!String.IsNullOrEmpty(ip))
    {
        predicate = predicate.OrElse(x => x.UserIp == ip);
    }

    UserInfo user = _userSessionService.CurrentUser();
    if (user != null)
    {
        predicate = predicate.OrElse(x => x.UserId == user.Id);
    }

    bool hasVoted = _articleService.GetLikes().Where(x => x.ArticleId == m.Id)
                                              .Where(predicate)
                                              .Any();

Этот код запускается, когда мне нужно проверить, нажал ли пользователь кнопку «Мне нравится» в статье. Для отслеживания пользователя я использую

  1. Ключ-шпион от cookie
  2. IP-адрес
  3. UserId, если он вошел в систему

Тот же код запускается, когда я запускаю ajax-вызов для вставки "подобного голоса" за статью в базе данных.

Так что я хотел бы заключить это в капсулу. Моя первая идея состояла в том, чтобы выбрать метод расширений, но мне это не нравится, поскольку мне придется прибегнуть к шаблону ServiceLocator, чтобы получить ссылки на подобные сервисы

IUserKeyService service = ServiceLocator.Current.GetInstance<IUserKeyService>();

Мне кажется, это был бы плохой дизайн, так как он не поддается проверке. Я хотел бы иметь класс, который можно использовать повторно и в то же время можно контролировать контейнером DI. Класс, в который я могу ввести зависимости. Возможно ли это?

...