RegisterPerWebRequestRegisterWithContext (这个最初并没有附带简单的注射器,但是它是在他们的 高级场景部分)。两种方法单独工作都很好,但我需要将它们结合起来。

我发现在 RegisterPerWebRequest 用过的 new WebRequestLifestyle() 生活方式(找到了 那里)。所以不要使用 Lifestyle.Transient RegisterWithContext 我提供了 new WebRequestLifestyle() 但看来 DependencyContext.ImplementationTypeDependencyContext.ServiceType 为空。

这有什么问题吗?

更新1。

所以我想按照网络请求注册类型 RegisterPerWebRequest 而且还能够为实例创建者提供对注入注册类型的类型的访问权限。

我修改了(提取生活方式作为参数) RegisterWithContext 成为:

public static void RegisterWithContext<TService>(
    this Container container,
    Func<DependencyContext, TService> contextBasedFactory, Lifestyle lifestyle)
    where TService : class
{
    //original code

    container.Register<TService>(rootFactory, lifestyle);

    //original code
}

对于“每个网络请求和上下文”注册,我希望能够使用:

container.RegisterWithContext<IUnitOfWork>(dependencyContext =>
{
      var implementationType = dependencyContext.ImplementationType;
      //do some stuff and return preconfigured UnitOfWork
}, new WebRequestLifestyle());

正如我已经提到的 dependencyContext.ImplementationTypeNULL

我正在使用 SimpleInjector 2.3.0.0

有帮助吗?

解决方案

RegisterWithContext 扩展方法显式地将提供的委托注册为 Transient. 。这样做是因为用任何其他生活方式注册该类型没有什么意义。

生活方式的想法,例如 WebRequestLifestyle 是在整个对象图中缓存并重用相同的实例(可能还不止于此)。然而,这个概念在处理基于上下文的注册时没有什么意义,因为基于上下文的实例每次注入时都应该是不同的。换句话说,为每个消费者提供唯一的实例与重用同一实例的概念相冲突。

例如,看一下下面的对象图:

new HomeController(
    new Logger("HomeController"),
    new LoggingRepositoryDecorator<User>(
        new Logger("LoggingRepositoryDecorator<User>"),
        new SqlRepository<User>(
            new DbContext())),
    new LoggingCommandHandlerDecorator<ShipOrder>(
        new Logger("LoggingCommandHandlerDecorator<ShipOrder>"),
        new ShipOrderCommandHandler(
            new DbContext())));

在此对象图中,我们创建一个 HomeController 及其依赖项。这 Logger 组件显然是一个基于上下文的组件,因为它每次都会根据其父级进行不同的初始化。这将是注册 Logger:

container.RegisterWithContext<ILogger>(context =>
    new Logger(context.ImplementationType.Name));

但如果我们允许 ILogger 注册 注册到 WebRequestLifestyle, ,每次都应该应用相同的实例,这可能会导致以下对象图:

ILogger logger = new Logger(typeName: "HomeController");

new HomeController(
    logger,
    new LoggingRepositoryDecorator<User>(
        logger,
        new SqlRepository<User>(
            new DbContext())),
    new LoggingCommandHandlerDecorator<ShipOrder>(
        logger,
        new ShipOrderCommandHandler(
            new DbContext())));

在此对象图中相同 Logger("HomeController") 被注入了,这显然不是我们想要的。此外,行为变得非常不可预测,因为首先创建的是消费者,这将决定记录器的 typeName 在整个图表中被重复使用。但没有人会想到删除 ILogger 来自 HomeController的构造函数,会导致记录器 LoggingCommandHandlerDecorator<ShipOrder> 改变。

这就是为什么没有 Lifestyle 论据中的 RegisterWithContext 扩展方法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top