Нужны советы по созданию условного параметра для инициализации класса с помощью DI, C # и Web API 2.0 - PullRequest
0 голосов
/ 01 января 2019

Я использую инъекцию зависимостей Unity и Web API 2.0.

У меня есть контроллер, которому я ввожу свою единицу работы:

public ProductController(IUnitOfWork unitOfWork)
{
    _unitOfWork = unitOfWork;
}

Затем у меня есть метод в этом контроллере:

public HttpResponseMessage UpdateProducts(string website)
{ 
   ProductAPI productAPI;
   Enum.TryParse(website, out Website website);

   productAPI = new ProductAPI(_unitOfWork, website);
   productAPI.UpdateProducts();
}

Метод принимаетвеб-сайт параметров, который является перечислением.Он имеет 3 различных значения (website1, website2, website3).

Это конструктор ProductAPI, который принимает UOW, и перечисление веб-сайта:

public ProductAPI(IUnitOfWork unitOfWork, Website website)
{
    _unitOfWork = unitOfWork;
    _website = website;
    _httpClient = CommonAPI.GetHttpClient(website);
}

Класс CommonAPI является статическим классом, которыйвозвращает httpclient на основе веб-сайта.

public static HttpClient GetHttpClient(Website website)
{
    HttpClient httpClient = new HttpClient();

    if (website == Website.1)
    {
        //return httpclient for website 1
    }
    else if (website == Website.2)
    {
        //return httpclient for website 2
    }
    else if (website == Website.3)
    {
        //return httpclient for website 3
    }

    return httpClient;
}

Класс ProductAPI также имеет вызовы в своих методах, которые используют UOW, но также используют перечисление веб-сайта для фильтрации на основе значения веб-сайта:

List<ProductViewModel> products = _unitOfWork.ProductRepository.GetProducts(_website.ToString());

Есть ли лучший и более чистый способ настроить этот код на основе перечисления этого сайта?

1 Ответ

0 голосов
/ 01 января 2019

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

Вызывающий абонент определяет, какой веб-сайт используется для обновления продуктов. Итак, размещение логики в контроллере имеет смысл.

В целом;может быть какой-то более высокий уровень абстракции, но код выглядит нормально, как есть.


Но если вы хотите испачкать руки: вы можете абстрагировать WebClient.

Например:

Определите общий интерфейс:

public interface IYourTypicalHandler{ /*def here */}

И реализуйте его:

public class Web1Client : IYourTypicalHandler, HttpClient  { /*logic here */ }
public class Web2Client : IYourTypicalHandler, HttpClient  { /*logic here */ }
public class Web3Client : IYourTypicalHandler, HttpClient  { /*logic here */ }

Теперь вы инкапсулировали и изолировали свое конкретное веб-поведение в разных классах.Это может использоваться как стратегия реализации для вашего ProductAPI.

Сначала создайте для него интерфейс:

public interface IProductApi { /* def here */ }

Подпись реализации будет:

 public class ProductAPI : IProductApi {
     public ProductAPI(IUnitOfWork unitOfWork, IYourTypicalHandler)
 }

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


Конечно, вам нужно перемонтировать фабрику:

//note: not bound to http anymore ;-)
public static IYourTypicalHandler GetHttpClient(Website website)

На данный момент у вас нет доступа к _website.ToString() in:

var products = _unitOfWork.ProductRepository.GetProducts(_website.ToString());

, который может усложнить ситуацию, а также может стать целью.Так что, это зависит от вас, если оно того стоит; -)

Надеюсь, это поможет.

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