3

我的解决方案中内置了一个专有事件模型,它有一个订阅实例化过程,该过程使用GetAllInstances()SimpleInjector 的方法来定位事件的所有订阅者

public IEnumerable<ISubscriber<T>> GetSubscriptions<T>()
    where T : IEvent
{
    return _container.GetAllInstances<ISubscriber<T>>();
}

根据我是否注册所有实例,我的性能会出现巨大ISubscriber差异

这是我用来注册的代码ISubscriber

internal void Configure(Container container)
{
    container.RegisterManyForOpenGeneric(
        typeof(ISubscriber<>),
        AccessibilityOption.PublicTypesOnly,
        (serviceType, implTypes) => 
            container.RegisterAll(serviceType, implTypes),
        AppDomain.CurrentDomain.GetAssemblies()
    );

    container.RegisterDecorator(typeof(ISubscriber<>), 
        typeof(SubscriberTraceDecorator<>));

    container.RegisterDecorator(typeof(ISubscriber<>), 
        typeof(SubscriberExceptionDecorator<>));
}

当我在没有调用RegisterManyForOpenGeneric容器验证的情况下引导容器时,大约需要 11 秒并返回结果:

配置警告:未检测到警告。

注册:计数 = 158

但是,当我取消注释对RegisterManyForOpenGeneric容器验证的调用大约需要 72 秒并返回结果时:

配置警告:已检测到 136 个容器注册类型,这些类型被 181 个组件引用

注册:计数 = 475

我的问题是——这样可以吗,还是我在这里做错了什么?我一直在添加更多ISubscriber的课程,现在启动(方式)太慢了......


更新

这似乎只是在 Visual Studio中运行的 WebAPI 项目的问题。从控制台应用程序引导需要 15 秒在 Visual Studio 中运行。将 WebAPI 项目部署到 IIS 后,验证需要 6 秒。

4

1 回答 1

1

如果不调用Verify(),Simple Injector 容器将在第一次请求委托时回退到一种“及时”的委托编译。在这种情况下,容器通常会构建一个委托来创建整个对象图(那个“根”对象+它的所有直接和间接依赖项)。由于委托是为整个对象图构建的,因此通常只编译一个委托。

将其与调用Container.Verify()方法进行比较。调用时,此方法会遍历所有注册并为每个注册请求一个实例。这会强制为容器中的每个注册编译委托(不仅针对直接请求的根类型)。

换句话说,调用有很多开销,Verify并且所有这些生成和编译都是在应用程序的启动阶段完成的,与您否则会得到的类似即时行为的行为相比。

启动期间的调用Verify()并不适合每个应用程序。完成所需的时间Verify()取决于许多因素,例如:

  • 机器的力量。
  • 无论您是否在调试器中运行。
  • 容器中的注册数。
  • 使用特殊功能。正如您所注意到的,应用装饰器会对编译过程产生影响。当装饰器包含泛型类型约束时尤其如此。

最好Verify()在启动期间始终调用,直到...

直到配置变得太大而无法调用Verify()。在这种情况下,您可以执行以下操作:

  1. 在附加调试器时防止调用Verify,因为这里的开销是最大的。
  2. Verify如果应用程序启动时间过长,请防止在生产启动期间调用。
  3. 创建一个调用引导程序代码的单元测试来请求配置的容器实例并让单元测试调用Verify()它。这可确保在将软件推出测试、验收或生产之前很久仍能发现配置错误。可验证的配置非常重要。
于 2013-04-15T19:34:09.350 回答