Как исправить циклическую ссылку в .NET Core DI

Натыкаюсь на циклическую ссылку от 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 не может решить такую ​​проблему, которую вы не смогли бы решить без нее.

500 - Internal Server Error 17.02.2023 03:39

Это очень сильный признак плохого дизайна. Циклическая ссылка вызвана самим кодом, а не DI. Вы не можете создавать такие объекты даже с помощью рукописных вызовов new, если вы не передадите null для CarService или RecallService

Panagiotis Kanavos 17.02.2023 09:14

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

Jason Pan 17.02.2023 09:15

Возможный дубликат: stackoverflow.com/questions/67725031/…

Steven 19.02.2023 18:27
Конечные и Readonly классы в PHP
Конечные и Readonly классы в PHP
В прошлом, когда вы не хотели, чтобы другие классы расширяли определенный класс, вы могли пометить его как final.
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
БЭМ: Конвенция об именовании CSS
БЭМ: Конвенция об именовании CSS
Я часто вижу беспорядочный код CSS, особенно если проект большой. Кроме того, я совершал эту ошибку в профессиональных или личных проектах и...
Революционная веб-разработка ServiceNow
Революционная веб-разработка ServiceNow
В быстро развивающемся мире веб-разработки ServiceNow для достижения успеха крайне важно оставаться на вершине последних тенденций и технологий. По...
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Заголовок веб-страницы играет наиболее важную роль в SEO, он помогает поисковой системе понять, о чем ваш сайт.
Конфигурация Jest в angular
Конфигурация Jest в angular
В этой статье я рассказываю обо всех необходимых шагах, которые нужно выполнить при настройке jest в angular.
1
4
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

По-своему, используйте 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 в вашем коде?

Jason Pan 17.02.2023 09:11

Я просто копирую из его кода. :-)

Soheil 17.02.2023 09:15

Привет, Сохейл, это не очень хорошая душа.

Jason Pan 17.02.2023 09:16

Я это знаю, но это работает. 🥴

Soheil 17.02.2023 09:40

Почему вы сказали, что разделение ваших услуг не является хорошим решением? Я бы сказал, что это их решение, как я выразился здесь, потому что оно исправляет нарушения SRP и ISP, которые есть в коде.

Steven 19.02.2023 18:30
Ответ принят как подходящий

Вы можете изменить свой код, как показано ниже, это поможет вам решить проблему циклических ссылок.

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);
        }
    }
}

Другие вопросы по теме