gpt4 book ai didi

c# - 获取 Simple Injector 的容器实例

转载 作者:可可西里 更新时间:2023-11-01 03:06:13 24 4
gpt4 key购买 nike

我在 ASP.NET MVC 项目中使用简单注入(inject)器。我添加了 SimpleInjector.Integration.Web.Mvc nuget 包。这会在 App_Start 文件夹中添加 SimpleInjectorInitializer 类并初始化 DI。代码看起来像

public static void Initialize()
{
// Did you know the container can diagnose your configuration?
// Go to: https://simpleinjector.org/diagnostics
var container = new Container();

//Container configuration code
DependencyResolver.SetResolver(
new SimpleInjectorDependencyResolver(container));
}

这为 MVC Controller 正确配置了 DI。

我的问题是,如果我想在任何 Controller \类中获取容器实例以手动解决某些依赖项,我该怎么做。

我之前曾在 AutoFac 上工作过,它有一个依赖接口(interface) IComponentContext,可以将其注入(inject)到任何需要手动执行任何解析的类中。

更新:

这是一个场景。我的 Controller 使用的服务初始化取决于 Controller 方法中传递的输入参数,因此在构建期间无法实例化依赖项。

我知道这在某种程度上是 DI 的反模式,但它在少数地方是必需的,因此注入(inject) DI 容器是下一个最佳选择。 Simple Injector 示例应该使用静态变量来共享我想避免的容器,而且 SimpleInjectorInitializer 的工作方式也不可能。

最佳答案

除了作为应用程序启动路径一部分的任何代码外,任何代码都不应直接依赖于容器(或容器抽象、容器外观等)。此模式称为 Service LocatorMark Seemann有一个good explanation为什么这是个坏主意。

因此组件(例如 Controller )不应直接依赖于容器,因为这会隐藏使用的依赖项并使类更难测试。此外,您的代码开始依赖于外部框架(使其更难更改)或依赖于它不需要了解的抽象。

My controller uses a service who initialization depends upon the input parameter passed in the controller method and hence the dependency cannot be instantiated during construction time

这个问题有一个通用模式:abstract factory design pattern .工厂模式允许您延迟类型的创建,并允许您为特定类型的构造传入额外的运行时参数。当您执行此操作时,您的 Controller 不必依赖于 Container,并且它可以防止您必须在单元测试中传入构造的容器(DI 框架通常不应在您的单元测试项目中使用)。

但是请注意,让您的组件需要 runtime data during creation is a code smell .防止这样做。

您可能认为这样做只是将问题转移到工厂实现中。虽然我们将对容器的依赖转移到工厂实现中,但实际上我们正在解决问题,因为工厂实现将成为应用程序的 Composition Root 的一部分。 ,它允许应用程序代码本身不受任何 DI 框架的影响。

这就是我建议您构建代码的方式:

// Definition of the factory in the UI or BL layer
public interface ISomeServiceFactory
{
ISomeService Create(int inputParameter);
}

// Controller depending on that factory:
public class MyController : Controller
{
private readonly ISomeServiceFactory factory;

public MyController(ISomeServiceFactory factory)
{
this.factory = factory;
}

public ActionResult Index(int value)
{
// here we use that factory
var service = this.factory.Create(value);
}
}

在您的组合根目录(启动路径)中,我们定义了工厂实现及其注册:

private class SomeServiceFactory : ISomeServiceFactory
{
private readonly Container container;

// Here we depend on Container, which is fine, since
// we're inside the composition root. The rest of the
// application knows nothing about a DI framework.
public SomeServiceFactory(Container container)
{
this.container = container;
}

public ISomeService Create(int inputParameter)
{
// Do what ever we need to do here. For instance:
if (inputParameter == 0)
return this.container.GetInstance<Service1>();
else
return this.container.GetInstance<Service2>();
}
}

public static void Initialize()
{
var container = new Container();

container.RegisterSingle<ISomeServiceFactory, SomeServiceFactory>();
}

创建后,Container注册自己(使用调用 RegisterSingle<Container>(this) )所以你总是可以将容器注入(inject)任何组件。这类似于注入(inject) IComponentContext使用 Autofac 时。但同样适用于 Autofac、Simple Injector 和任何其他容器:您不想将您的容器注入(inject)到位于组合根之外的组件中(而且几乎没有理由这样做)。

关于c# - 获取 Simple Injector 的容器实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17906423/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com