Каков наилучший способ обработки HTTP-соединений в пользовательской модели класса в Net Core?

У меня есть модель класса, использующая дизайн шаблона GRASP, в частности шаблон контроллера, поэтому ProductController обрабатывает все экземпляры Product, а этот обрабатывает все экземпляры Kardex.

ProductController может сохранять, редактировать и удалять продукты.
Product может сохранять и удалять движения kardex.

введите здесь описание изображения

Я могу справиться с этим только с помощью ООП, но мне нужно, чтобы некоторые методы вызывали API для сохранения и/или получения данных из БД.

Мое приложение будет постоянно выполнять операции с этим API, поэтому я решил использовать IHttpClientFactory с DI.

Если я ввожу контроллеры с их соответствующими интерфейсами, это не проблема, но если экземпляр продукта должен SaveKardex, мне придется вводить его для использования HttpClientFactory, предотвращая создание экземпляра. Итак, я сделал это:

public class Product
{
  private readonly IHttpClientFactory _httpClientFactory;
  public int prop1 { get; set; }
  
  public Product(IHttpClientFactory httpClientFactory) //this works
  {
     _httpClientFactory = httpClientFactory;
  }
  
  public Product() //this also works
  {
     prop1 = 10;
  }

  public async Task<bool> SaveKardex(Kardex kardex)
  {
     var client = _httpClientFactory.CreateClient("BdClient");
     var uriString = client.BaseAddress + $"product/kardex";
     var message = RequestBuilder.RequestMessage(HttpMethod.Post, uriString);
     var res = await client.SendAsync(message);
     ....
     ....
     return true;
  }
}

Если я создам экземпляр нового Product или будет десериализован, я не смогу вызвать метод SaveKardex, потому что я не буду использовать введенный экземпляр, а httpClientFactory будет нулевым.

Что я могу сделать? Какие-либо предложения?

Я думал об использовании экземпляров HttpClient, но лучший ли это способ, учитывая большое количество подключений к API?

Спасибо!


person Gonzalo Bustamante    schedule 19.05.2021    source источник
comment
Не пытайтесь сделать ваши модели объектами DI. Отделите одно от другого. Имейте ProductModel, который является более или менее POCO, и пусть службы DI используют их.   -  person Andy    schedule 19.05.2021
comment
Ваша модель страдает от тесной связи и низкой связности.   -  person Nkosi    schedule 19.05.2021


Ответы (1)


Я решил эту переделку своей модели следующим образом: (как сказал @Nkosi, это страдало от жесткой связи и низкой сплоченности).

Был создан EntityLayer со всеми свойствами, которые будут отправлены в BD и наоборот.

Создан Интерфейс, в котором объявлены операции с БД.

Был создан класс службы, реализующий интерфейс. Этот класс внедряется в ядро ​​.net, а не в другое.

Наконец, все экземпляры Product получают этот интерфейс (который реализуется ProductService), поэтому таким образом я могу вызывать операции bd.

public class EntityProduct
{
  public int prop1 {get; set; }
}

public interface IProductOperations
{
  Task<bool> SaveKardex(int prop);
}

public class ProductService : IProductOperations //only this class is inyected
{
  private IHttpClientFactory httpClientFactory;
  public ProductService(IHttpClientFactory httpClientFactory)
  {
     this.httpClientFactory = httpClientFactory;
  }

  public async Task<bool> SaveKardex(int prop)
  {
     var client = _httpClientFactory.CreateClient("BdClient");
     var uriString = client.BaseAddress + $"product/kardex/{prop}";
     var message = RequestBuilder.RequestMessage(HttpMethod.Post, uriString);
     var res = await client.SendAsync(message);
     ....
     ....
     return true;
  }
}

public class Product
{
  private IProductOperations _productOperations;
  public EntityProduct Entity { get; set; }
  
  public Product(IProductOperations productOperations)
  {
     _productOperations = productOperations;
  }
  
  public async Task<bool> SaveKardex(int prop)
  {
     var result = await _productOperations.SaveKardex(prop);
     ....
     ....
     return true;
  }
}

Я смог сделать это благодаря этому ответу от @robert-paulen

person Gonzalo Bustamante    schedule 22.05.2021
comment
Я думаю, вы неправильно смоделировали отношения. Почему Product должен зависеть от ProductOperations? ProductService должен работать с Products. - person Peter Csala; 26.05.2021
comment
Это единственный способ, который я нашел. Как вызвать SaveKardex из Продукта? ProductService реализует этот интерфейс, а Product использует эту реализацию для вызова API. Любые предложения приветствуются - person Gonzalo Bustamante; 27.05.2021
comment
Если я могу предположить, что Product.SaveKardex — это просто оболочка вокруг ProductService.SaveKardex, то все, что вам нужно сделать, это: полностью избавиться от класса Product и передать EntityProduct классу SaveKardex: Task<bool> SaveKardex(EntityProduct product);. Поэтому ProductContoller должно зависеть от ProductService. - person Peter Csala; 27.05.2021