Первое, что я узнаю о том, что вы показываете выше, это то, что вы используете шаблон Service Locator, а не Inpendency Injection, и учитывая, что вы используете ASP NET Core DI-контейнер ( или, похоже, после короткого взгляда на вашу кодовую базу) это делает ваш код намного сложнее, чем нужно.
Во время запуска вы регистрируете все службы, которые могут потребоваться вызывать на протяжении всего процесса. ваш код, но тогда вы не верите, что контейнер сервисов получит те сервисы, где им нужно go, когда вы создаете экземпляры классов и вместо этого пытаетесь go выследить его.
Спецификация c Проблема, с которой вы столкнулись, заключается в том, что вы пытаетесь установить какой-то глобальный, статический c экземпляр IServiceProvider, но вы никогда не добавляете в него какие-либо службы. Поскольку у вас нет установщика, в первый раз, когда один из ваших локаторов пытается получить что-то с помощью вспомогательного класса stati c, он сообщает о пустой коллекции и возвращает ее, и этот экземпляр полностью отделен от того, который вы регистрировали во время Запуск.
Тем не менее, некоторая реструктуризация была бы лучшим путем, чем "исправление" этого глобального вспомогательного экземпляра stati c. Рассмотрим следующий код:
public class Foo
{
public int Bar;
public int Qux;
}
public interface IRepository<T> where T : class, new()
{
T GetEntity();
}
public class FooRepository : IRepository<Foo>
{
public Foo GetEntity()
{
return new Foo();
}
}
public abstract class BaseService<TEntity>
where TEntity : class, new()
{
protected readonly IRepository<TEntity> _entityRepository;
protected readonly IMapper _mapper;
protected BaseService(IRepository<TEntity> entityRepository, IMapper mapper)
{
_entityRepository = entityRepository;
_mapper = mapper;
}
}
public interface IFooService
{
Foo ServicyStuff();
}
public class FooService : BaseService<Foo>, IFooService
{
public FooService(IRepository<Foo> entityRepository, IMapper mapper) : base(entityRepository, mapper)
{
}
public Foo ServicyStuff()
{
var foo = _entityRepository.GetEntity(); // Our abstract class handled this for us!
return foo;
}
}
И следующие регистрации служб при запуске:
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
services.AddTransient<IRepository<Foo>, FooRepository>();
services.AddTransient<IFooService, FooService>();
Теперь мы можем просто передать экземпляр IFooService в контроллеры или другие службы с поддержкой DI и все остальное все подключено и готово к go. Когда IFooService разрешает FooService, FooService разрешает хранилище и использует абстрактный базовый класс, чтобы гарантировать, что хранилище внедрено и доступно для унаследованных классов во время создания экземпляра. Контейнер DI отвечает за всю тяжелую работу, которую вы пытаетесь выполнить с помощью абстрактного класса и расширений локатора услуг.
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IFooService _fooService;
public HomeController(ILogger<HomeController> logger, IFooService fooService)
{
_logger = logger;
_fooService = fooService;
}
public IActionResult Index()
{
var myFoo = _fooService.ServicyStuff();
return View();
}