Я начал замечать, что мой код построения предиката выглядит примерно так. Это знак для рефакторинга. Давайте посмотрим на код.
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();
Этот код запускается, когда мне нужно проверить, нажал ли пользователь кнопку «Мне нравится» в статье.
Для отслеживания пользователя я использую
- Ключ-шпион от cookie
- IP-адрес
- UserId, если он вошел в систему
Тот же код запускается, когда я запускаю ajax-вызов для вставки "подобного голоса" за статью в базе данных.
Так что я хотел бы заключить это в капсулу. Моя первая идея состояла в том, чтобы выбрать метод расширений, но мне это не нравится, поскольку мне придется прибегнуть к шаблону ServiceLocator, чтобы получить ссылки на подобные сервисы
IUserKeyService service = ServiceLocator.Current.GetInstance<IUserKeyService>();
Мне кажется, это был бы плохой дизайн, так как он не поддается проверке. Я хотел бы иметь класс, который можно использовать повторно и в то же время можно контролировать контейнером DI. Класс, в который я могу ввести зависимости.
Возможно ли это?