C# 有没有一种方法可以预构建我在Simple Injector容器中注册的所有服务?

C# 有没有一种方法可以预构建我在Simple Injector容器中注册的所有服务?,c#,asp.net-core,simple-injector,C#,Asp.net Core,Simple Injector,在部署或IIS管理器重新启动后,我正试图缩短服务器的初始请求时间。当我在寻找一种方法来做到这一点时,我偶然发现了这篇文章。然而,我的项目使用(SI)库-我不确定如何(如果可能的话)指示SI预构建我的注册服务,这将提高第一次请求的时间 以前有人试过吗 这是我的Startup.cs public class Startup { private IHostingEnvironment _env; private static readonly Container _container

在部署或IIS管理器重新启动后,我正试图缩短服务器的初始请求时间。当我在寻找一种方法来做到这一点时,我偶然发现了这篇文章。然而,我的项目使用(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);
    }
}
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);
    }
}

您链接的文章只是在启动时创建每个服务的一个实例,而不管它是单例的、有范围的还是暂时的

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

[是否可能]指示SI预构建我的注册服务,这将提高首次请求时间

是的,有配置容器后,应调用
容器。验证()

除其他事项外,verify将迭代所有已知的注册,创建并编译它们的表达式树

默认情况下,
Verify
执行许多操作:

  • 它为所有注册构建所有表达式树
  • 它将这些表达式树编译为委托
  • 它调用这些委托以确保可以创建实例。这样,它强制JIT编译器编译委托
  • 它将迭代容器控制的集合,因为它们在简单注入器中表现为流
  • 它将确保在decorator包含decorateee工厂的情况下创建decorateee
  • 它将在对象图上运行完整诊断
有一个超负荷的
Verify
,允许您取消最后一个诊断步骤。但请注意,您通常不应禁止诊断

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


有关更多信息,请参阅上的文档和。

有关解决方案的三个注意事项:1。除非将操作包装在活动作用域中,否则此代码可能无法工作。2.当您调用了
container.Verify()
之后,就不再需要执行此循环,因为这是Verify实际执行的操作之一。3.您的解决方案不会编译所有内容,例如,集合仍然是惰性读取的<代码>验证,另一方面,确保注册的集合也将被编译和测试。感谢您纠正我的错误,不敢相信我没有考虑范围位,因为这是在启动代码中,而不是请求中。从未考虑过
Verify
呼叫在内部执行的操作,tbh。感谢您的详细回答!我没有意识到,
verify
可以做到这一切,实际上,由于方法的名称,我没有想到会这样。我想我应该先检查一下文档中的方法:)将
verify()
作为启动例程的固定部分,可以让我们避免很多潜在的麻烦。应该是所有DI容器上的标准功能。请注意,Andrew Lock描述的迭代ServiceCollection的方法很容易崩溃并阻止应用程序启动,因为您会发现框架和第三方注册有时处于部分正确的状态,并根据用户配置完成。ServiceCollection注册不需要正确,这使得迭代ServiceCollection很困难。一开始可能有用,但在更新软件包或添加新软件包后会出现故障。感谢您的建议,Steven!乍一看,Andrew建议的方法似乎是一个非常好的主意,但现在我倾向于不接触我的当前配置:)预构建ServiceCollection:坏主意。预制简单注射器:非常好。