每个Web请求和上下文的简单注入器寄存器

时间:2014-02-27 17:23:07

标签: c# dependency-injection simple-injector

RegisterPerWebRequestRegisterWithContext(这个版本最初不附带简单的注入器,但是它在advanced-scenarios section上提供)。另外两种方法都可以正常工作,但我需要将它们结合起来。

我发现RegisterPerWebRequest使用了new WebRequestLifestyle()生活方式(找到它there)。因此,我提供Lifestyle.Transient而不是RegisterWithContext new WebRequestLifestyle(),但DependencyContext.ImplementationTypeDependencyContext.ServiceType似乎为空。

这有什么问题?

更新1。

所以我想像RegisterPerWebRequest一样注册每个Web请求的类型,但也能够为实例创建者提供访问注册类型的类型的访问权。

我修改了(将生活方式作为参数提取)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

1 个答案:

答案 0 :(得分:8)

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())));

在这个对象图中,我们创建了一个带有依赖关系的HomeControllerLogger组件显然是基于上下文的组件,因为它每次都基于其父级进行不同的初始化。这将是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参数的原因。

相关问题