Я разрабатываю SDK и использую DI (я думаю, что неправильно) для своих классов и их зависимостей. Я считаю, что я смешал DI и сервисный локатор Мои проблемы:
- Зная, где построить мой DI-контейнер. У меня нет среды выполнения / точки входа для использования в качестве корня композиции - и не должен в соответствии с этим постом.
- Срок службы. То, как я создаю свой DI-контейнер, вызывает создание нескольких одноэлементных объектов, и каждый класс имеет свой собственный DI-контейнер - я определенно хочу избежать этого
Этот DI через Builder эквивалентен шаблону поиска служб? , кажется, то, что я ищу, но без ответа.
Я определяю свой контейнер с помощью .NET DI:
public class ServiceProvider
{
private Microsoft.Extensions.DependencyInjection.ServiceProvider serviceProvider;
protected readonly IServiceCollection serviceCollection = new ServiceCollection();
public ServiceProvider()
{
serviceCollection.AddScoped<IScopedService, ScopedService>();
serviceCollection.AddSingleton<ISingletonService, SingletonService>();
}
}
Теперь, когда ScopedService зависит от SingletonService, это делается с помощью правильного внедрения конструктора:
public ScopedService(ISingletonService singletonService)
{
_singletonService = singletonService
}
Но классы потребления (конечного пользователя) выполняются через локатор службы, например,
private IScopedService _scopedService;
private IScopedService ScopedService
{
get
{
return _scopedService ?? _scopedService = serviceProvider.GetService<IScopedService>();
}
}
Все мои потребительские классы наследуются от базового класса, который, я считаю, создает новый экземпляр ServiceProvider каждый раз, когда создается экземпляр класса.
public abstract class ComponentBase
{
protected internal ServiceProvider serviceProvider = new ServiceProvider();
}
Проблема: создается несколько объектов Singleton
var singleton1 = consumingClass.serviceProvider.GetService<ISingletonService>();
var singleton2 = consumingClass.serviceProvider.GetService<ISingletonService>();
Assert.AreEqual(singleton1, singleton2) // Test failure
Я ожидаю, что службы Singleton будут одним и тем же экземпляром. Должен ли я сделать ServiceProvider в базовом классе статическим? Это решило бы проблему, но также, кажется, имеет тенденцию еще больше в направлении анти-паттерна поиска сервисов.
Должен ли я перейти к заводскому шаблону? Где я регистрирую все потребляющие классы в поставщике услуг, и только фабрика знает о контейнере DI? Вы бы тогда получили класс, вызвав геттера на заводе?