【发布时间】:2019-11-03 12:59:33
【问题描述】:
我正在开发一个 SDK,并在我的类及其依赖项中使用 DI(我认为是错误的)。我相信我已经混合了 DI 和服务定位器。我的问题是:
- 知道在哪里构建我的 DI 容器。我没有可用作composition root 的运行时/入口点 - 并且不应该根据该帖子。
- 服务生命周期。我创建 DI 容器的方式会导致创建多个单例对象,并且每个类都有自己的 DI 容器 - 我绝对想避免这种情况
这个DI via Builder equivalent to service locator anti-pattern? 似乎是我所追求的,但没有得到答复。
我用 .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();
}
问题:正在创建多个单例对象
var singleton1 = consumingClass.serviceProvider.GetService<ISingletonService>();
var singleton2 = consumingClass.serviceProvider.GetService<ISingletonService>();
Assert.AreEqual(singleton1, singleton2) // Test failure
我希望 Singleton 服务是同一个实例。我应该将基类中的 ServiceProvider 设为静态吗?这将解决问题,但似乎也朝着服务定位器反模式的方向发展。
我应该转向基于工厂的模式吗?我在服务提供者中注册所有消费类并且只有工厂知道 DI 容器?然后你会通过调用工厂的 getter 来获得一个类?
【问题讨论】:
-
虽然 IMO 在某些情况下,类似于服务定位器的东西是两害相权取其轻的东西,但直接将容器注入到一个类中绝对是一种反模式,因为依赖关系变得不明确。该类可以从该容器请求anything。它创建了一个未定义的、开放式的依赖关系。 Here's an article(我的)展示了一个示例,其中服务定位器之类的东西可能会有所帮助,以及如何将其危害降到最低。
-
我会编写每个类来依赖它应该依赖的内容。如果你这样做,几乎总有一种方法可以配置你的容器以提供这些依赖项。这通常很容易。如果这很难,那么这就是要解决的问题。您的课程将正确编写。解决问题所在,而不是让它泄漏到你的类中。
-
谢谢@scotthannen,这是一篇非常有用的文章
-
请不要通过破坏您的帖子为他人增加工作量。通过在 Stack Overflow 上发帖,您已根据CC BY-SA 3.0 license 授予 SO 分发该内容的不可撤销的权利。根据 SO 政策,任何破坏行为都将被撤销。如果您想了解更多关于删除帖子的信息,请访问How does deleting work?
标签: c# dependency-injection .net-core