有没有办法预先构建我在 Simple Injector 容器中注册的所有服务?

Is there a way to pre-build all of my services that are registered with the Simple Injector container?

我正在尝试在 IIS 管理器部署或重新启动后立即缩短服务器的初始请求时间。当我正在寻找一种方法时,我遇到了这篇文章 Reducing initial request latency by pre-building services in a startup task in ASP.NET Core. However, my project uses the Simple Injector (SI) 库 - 我不确定如何(如果可能的话)指示 SI 预先构建我的注册应改善首次请求时间的服务。

有人试过吗?

那是我的Startup.cs

public class Startup
{
    private IHostingEnvironment _env;
    private static readonly Container _container = new Container();

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; private set; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMemoryCache();
        services.AddSession();
        services.Configure<AzureBlobSettings>(settings =>
            Configuration.GetSection("AzureBlobSettings").Bind(settings));

        IntegrateSimpleInjector(services);
    }

    private void IntegrateSimpleInjector(IServiceCollection services)
    {
        _container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        services.AddSingleton<IControllerActivator>(
            new SimpleInjectorControllerActivator(_container));
        services.AddSingleton<IViewComponentActivator>(
            new SimpleInjectorViewComponentActivator(_container));

        services.EnableSimpleInjectorCrossWiring(_container);
        services.UseSimpleInjectorAspNetRequestScoping(_container);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        _env = env;
        InitializeContainer(app, env);

        // standard config

        _container.Verify();

        // standard config

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}"
                );
            routes.MapRoute(
                name: "openSpotfire",
                template:
                "{controller=OpenAnalytics}/{action=AnalyticsView}/{id?}/{name?}"
                );
        });
    }

    private void InitializeContainer(
        IApplicationBuilder app, IHostingEnvironment env)
    {
        // Add application presentation components:
        _container.RegisterMvcControllers(app);
        _container.RegisterMvcViewComponents(app);

        // Add application services. 
        ServiceConfiguration.ConfigureService(_container, Configuration, env);

        // Allow Simple Injector to resolve services from ASP.NET Core.
        _container.AutoCrossWireAspNetComponents(app);
    }
}

那是我的ServiceConfiguration.cs

public static class ServiceConfiguration
{
    public static void ConfigureService(
        Container c, IConfiguration configuration, IHostingEnvironment env)
    {
        //Cross Cutting Concerns from nuget
        container.Register<CurrentUser>(Lifestyle.Scoped);
        container.Register<IUserProfileService, CachedUserProfileService>(
                Lifestyle.Scoped);
        container.Register<ISharedItemBuilderFactory, SharedItemBuilderFactory>(
            Lifestyle.Scoped);
        container.Register<IEmailer, DbMailer>(Lifestyle.Scoped);
        container.Register<IRecipientService, RecipientService>(Lifestyle.Scoped);
        container.Register<ISpotfireUserDataService, SpotfireUserDataService>(
            Lifestyle.Scoped);
        container.Register<IWorkbookManagementService, WorkbookManagementService>(
            Lifestyle.Scoped);
        container.Register<ILogger, NLogLogger>(Lifestyle.Scoped);

        // CCC Settings
        container.Register(() => new DbMailConnection
        {
            ConnectionString = configuration["AppSettings:ConnectionString"],
            Profile = configuration["AppSettings:DbMailProfile"]
        }, Lifestyle.Singleton);
    }
}

您链接的文章只是在启动时为每个服务创建一个实例,无论它是单例的、作用域的还是瞬态的。

编辑:删除了代码,因为有更好的解决方案

[is it possible] to instruct SI to pre-build my registered services which should improve the first request time.

是的,有。 你应该在配置容器后调用 Container.Verify()

除其他外,验证遍历所有已知的注册,创建并编译它们的表达式树。

默认情况下,Verify 会做很多事情:

  • 它为所有注册构建所有表达式树
  • 它将那些表达式树编译成委托
  • 它调用那些委托来确保可以创建实例。这样,它强制 JIT 编译器编译委托
  • 它将迭代 container-controlled 集合,因为它们在简单注入器中表现为流
  • 如果装饰器包含装饰器工厂,它将确保创建装饰器。
  • 它将运行对您的对象图进行全面诊断

有可用的 Verify 过载,允许您取消最后的诊断步骤。但请注意,您通常不应抑制诊断。

除了减少执行前几个请求所需的时间外,建议调用验证,因为它通过 运行 诊断服务检查配置的健康状况。这是将 Simple Injector 与 .NET 的所有其他 DI 容器区分开来的独特功能。

有关详细信息,请参阅文档 Verify the container’s configuration and on diagnostics