Натыкаюсь на циклическую ссылку от DI на мои бизнес-сервисы. Не уверен, что лучший способ сделать это. К сожалению, я не могу удалить ни из одной службы, так как они мне нужны в обеих.
Ниже приведен пример моей проблемы (не моих реальных услуг).
Автосервис
public class CarService
{
private readonly CarRepository _carRepository;
private readonly RecallService _recallService;
public CarService(CarRepository carRepository, RecallService recallService)
{
_carRepository = carRepository;
_recallService = recallService
}
public void RemoveRecallForCar(Recall recall)
{
//code
}
public void SendRecall(Guid carGuid)
{
Car car = _carRepository.Get(carGuid);
if (car.Model == "Ford")
{
_recallService.SendRecall(carGuid);
}
}
}
}
ОтзывСервис
public class RecallService
{
private readonly RecallRepository _recallRepository;
private readonly CarService _carService;
public RecallService(RecallRepository recallRepository,CarService carService)
{
_recallRepository = recallRepository;
_carService = carService
}
public void SendRecall(Guid carGuid)
{
// recall code
}
public GetRecalls()
{
List<Recall> recalls = _recallRepository.Fetch(x => x.IsActive).ToList();
foreach(var recall in recalls)
{
_carService.RemoveRecallForCar(recall);
}
}
}
}
Я ожидаю, что смогу внедрять сервисы в сервисы без циклических ссылок
Это очень сильный признак плохого дизайна. Циклическая ссылка вызвана самим кодом, а не DI. Вы не можете создавать такие объекты даже с помощью рукописных вызовов new, если вы не передадите null для CarService или RecallService
Мы можем абстрагироваться от функциональности, от которой зависит служба, введя интерфейс.
Возможный дубликат: stackoverflow.com/questions/67725031/…
По-своему, используйте Autofac или другую библиотеку DI.
Другой способ, который не является хорошим решением, заключается в том, что вы можете разделить свои услуги на несколько служб.
АвтоСервис1 :
public class CarService1
{
private readonly CarRepository _carRepository;
public CarrContactService(CarRepository carRepository)
{
_carRepository = carRepository;
}
public void RemoveRecallForCar(Recall recall)
{
//code
}
}
АвтоСервис2:
public class CarService2
{
private readonly CarRepository _carRepository;
private readonly RecallService _recallService;
public CarrContactService(CarRepository carRepository, RecallService recallService)
{
_carRepository = carRepository;
_recallService = recallService
}
public void SendRecall(Guid carGuid)
{
Car car = _carRepository.Get(carGuid);
if (car.Model == "Ford")
{
_recallService.SendRecall(carGuid);
}
}
}
Сервис отзыва:
public class RecallService
{
private readonly RecallRepository _recallRepository;
private readonly CarService1 _carService;
public RecallService(RecallRepository recallRepository,CarService1 carService)
{
_recallRepository = recallRepository;
_carService = carService
}
public void SendRecall(Guid carGuid)
{
// recall code
}
public GetRecalls()
{
List<Recall> recalls = _recallRepository.Fetch(x => x.IsActive).ToList();
foreach(var recall in recalls)
{
_carService.RemoveRecallForCar(recall);
}
}
}
Что такое CarrContactService в вашем коде?
Я просто копирую из его кода. :-)
Привет, Сохейл, это не очень хорошая душа.
Я это знаю, но это работает. 🥴
Почему вы сказали, что разделение ваших услуг не является хорошим решением? Я бы сказал, что это их решение, как я выразился здесь, потому что оно исправляет нарушения SRP и ISP, которые есть в коде.
Вы можете изменить свой код, как показано ниже, это поможет вам решить проблему циклических ссылок.
ICustomService.cs
public interface ICustomService
{
void SendRecall(Guid carGuid);
void RemoveRecallForCar(Recall recall);
}
RecallService.cs
public class RecallService : ICustomService
{
private readonly RecallRepository _recallRepository;
private readonly CarService _carService;
public RecallService(RecallRepository recallRepository, CarService carService)
{
_recallRepository = recallRepository;
_carService = carService;
}
public void SendRecall(Guid carGuid)
{
}
public GetRecalls()
{
List<Recall> recalls = _recallRepository.Fetch(x => x.IsActive).ToList();
foreach(var recall in recalls)
{
_carService.RemoveRecallForCar(recall);
}
}
public void RemoveRecallForCar(Recall recall)
{
}
}
CarService.cs
public class CarService
{
private readonly CarRepository _carRepository;
private readonly ICustomService _customService;
public CarService(CarRepository carRepository, ICustomService customService)
{
_carRepository = carRepository;
_customService = customService;
}
public void RemoveRecallForCar(Recall recall)
{
}
public void SendRecall(Guid carGuid)
{
Car car = _carRepository.Get(carGuid);
if (car.Model == "Ford")
{
_customService .SendRecall(carGuid);
}
}
}
Вы не можете иметь это. DI не может решить такую проблему, которую вы не смогли бы решить без нее.