Можно ли выполнить код после создания ServiceProvider? - PullRequest
0 голосов
/ 01 мая 2020

У меня есть ASP. NET Core 3.1 WebApi, основанный проект, который написан на C#. Я хочу выполнить код один раз, когда приложение завершит загрузку.

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

. Я подумал, используя .AddOptions() в расширение IServiceCollection позволит мне определить функцию, которая будет позже вызываться после создания IServiceProvider. Но, похоже, это не так.

Вот что я сделал. В методе ConfigureServices(IServiceCollection services) я добавил следующий код

services.AddOptions()
        .Configure<IServiceProvider>((serviceProvider) =>
        {
            var items = serviceProvider.GetServices<ICustomInterface>();

            foreach (ICustomInterface item in items)
            {
                item.DoSome();
            }
        });

Однако код внутри Configure<IServiceProvider>() никогда не вызывается.

Как я могу вызвать свой пользовательский код после IServiceProvider построен?

Ответы [ 2 ]

1 голос
/ 03 мая 2020

Если вы видели исходный код DefaultServiceProviderFactory , тогда да, вы можете иметь свой собственный ServiceProviderFactory , действующий по умолчанию и получающий преимущества to execute code after the ServiceProvider is created.

ExampleServiceProviderFactory.cs

public class ExampleServiceProviderFactory : IServiceProviderFactory<IServiceCollection>
{
    private readonly ServiceProviderOptions _options;

    public ExampleServiceProviderFactory(ServiceProviderOptions options)
    {
        if (options == null)
            throw new ArgumentNullException(nameof(options));

        _options = options;
    }

    public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder)
    {
        var serviceProvider =  containerBuilder.BuildServiceProvider(_options);

        // TODO: here you go
        var items = serviceProvider.GetServices<ICustomInterface>();

        foreach (ICustomInterface item in items)
        {
            item.DoSome();
        }

        return serviceProvider;
    }
}

Более простой и быстрый способ использовать этот ServiceProviderFactory вместо DefaultServiceProviderFactory для статута будет выглядеть так:

Program.cs

Host.CreateDefaultBuilder(args)
    .UseServiceProviderFactory((context) =>
    {
        var options = new ServiceProviderOptions()
        {
            ValidateOnBuild = false, // default,
            ValidateScopes = context.HostingEnvironment.IsDevelopment(),
        };
        return new CustomServiceProviderFactory(options);
    })
0 голосов
/ 02 мая 2020

Рассмотрим ваш program.cs файл. Как правило, здесь отображается код .....Build().Run() для запуска веб-службы.

Если вы разделите фазы сборки и запуска, вы сможете оценить поставщика услуг до того, как служба начнет обслуживать запросы.

            var host = Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                }).Build();

            // Do your initialization here
            var serviceProvider = host.Services;

            var items = serviceProvider.GetServices<ICustomInterface>();

            foreach (ICustomInterface item in items)
            {
                item.DoSome();
            }

            // Start your service
            host.Run();

...