Есть ли способ предварительно собрать все мои сервисы, которые зарегистрированы в контейнере Simple Injector? - PullRequest
3 голосов
/ 17 мая 2019

Я пытаюсь улучшить начальное время запроса моего сервера сразу после развертывания или перезапуска диспетчером IIS. Когда я искал способ сделать это, я наткнулся на эту статью Сокращение начальной задержки запроса путем предварительной сборки служб в задаче запуска в ASP.NET Core . Тем не менее, мой проект использует библиотеку 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);
    }
}

Ответы [ 2 ]

5 голосов
/ 17 мая 2019

[возможно ли] поручить СИ предварительно построить мои зарегистрированные сервисы, что должно улучшить время первого запроса.

Да, есть. Вы должны позвонить Container.Verify() после того, как настроили контейнер.

Помимо прочего, validate проходит через все известные регистрации, создает и компилирует их деревья выражений.

По умолчанию Verify делает несколько вещей:

  • Он строит все деревья выражений для всех регистраций
  • Он компилирует эти деревья выражений в делегаты
  • Он вызывает этих делегатов для обеспечения возможности создания экземпляров. При этом он заставляет JIT-компилятор компилировать делегаты
  • Он будет повторять управляемые контейнером коллекции, поскольку они ведут себя как потоки в Simple Injector
  • Это обеспечит создание декораторов в случае, если декоратор содержит фабрику декораторов.
  • Он запустит полную диагностику на вашем графе объектов

Имеется перегрузка Verify, позволяющая отключить последний шаг диагностики. Но учтите, что обычно вам не следует подавлять диагностику.

Помимо сокращения времени, необходимого для выполнения первых нескольких запросов, рекомендуется вызывать метод verify, поскольку он проверяет работоспособность вашей конфигурации, запуская диагностические службы. Это уникальная функция, которая отделяет Simple Injector от всех других контейнеров DI для .NET.

Для получения дополнительной информации см. Документацию Проверьте конфигурацию контейнера и включите Диагностика .

3 голосов
/ 17 мая 2019

Статья, которую вы связали, просто создает экземпляр каждой службы при запуске, независимо от того, является ли она одноэтапной, ограниченной или временной.

Редактировать: Удален код, потому что есть лучшее решение https://stackoverflow.com/a/56183491/928483

...