【发布时间】:2016-11-16 15:41:03
【问题描述】:
ASP.NET DI 开箱即用并递归解决所有构造函数依赖项非常棒。尽管有时您希望能够直接访问 DI 容器。我想知道有没有办法?也许是这样的:
IService service = Container.Instance.Resolve<IService>();
我在docs 中没有找到任何东西(虽然我知道,我可以替换内置的 DI 框架)。
在大多数情况下您不需要它,但有一些特定的情况。在我的情况下,我需要在应用启动时使用 IoC 容器初始化我的 EF DbContext,以启动应该与 EF Core 一样工作的自动迁移:
using (var context = new MyContext())
{
context.Database.Migrate();
}
我的上下文已在容器中注册,但它位于单独的类库中。而且我不想直接称它为DbContextOptions构造函数。
【问题讨论】:
-
非常不鼓励使用这种做法,因为它基本上首先扼杀了拥有 IoC 的所有好处,并有效地成为一种服务定位器模式,这是一种反模式(它隐藏了依赖关系) .了解为什么您想要这样做会更有趣。在 99% 的情况下,这只是一个糟糕的设计,而在 ASP.NET Core 的上下文中,我想不出有一个必要的情况,否则无法解决
-
@Tseng 我同意你的看法。如果应用程序设计良好,则解决方案会从控制器到整个系统的存储库。但也有具体案例。在我的特殊情况下,我想在启动时使用 DI 初始化我的 EF DbContext 以启动自动迁移。它发生在启动时,而不是请求到达控制器时。
-
关键词——“启动时”。当您在启动期间解决来自容器的依赖项时,这就是您的组合根。这正是它所属的地方。请参阅 this post 在启动时从容器中解析过滤器,由 Mark Seemann 编写(关于 .NET 中的依赖注入的官方真正聪明的人。)
-
@ScottHannen 哦,我知道它属于哪里。我只是想弄清楚我是否可以在不重复自己的情况下更好地接近它。我的意思是我不想在系统中有两个地方来初始化我的上下文。 1 号位置是 IServiceCollection 注册,2 号位置是我运行迁移的位置。显然我必须为上下文创建编写工厂,我希望有一种方法可以直接使用 IoC,但看起来没有。
-
@Anrei M - 这实际上是为那些说从容器中明确解决任何事情不正确的人准备的。只是指出当它位于组合根时它不是服务定位器模式。
标签: c# dependency-injection asp.net-core .net-core di-containers