Интеграция простого инжектора с HostBuilder в .NET Core 2.x - PullRequest
0 голосов
/ 19 сентября 2018

Мы разрабатываем службу Windows, которая запускает .net core 2.x.После этого сообщения в блоге Стива Гордона , выполняющего общие хост-приложения .netcore в качестве службы вещи работают прекрасно ... до тех пор, пока мы используем IServiceCollection.Я предпочитаю SimpleInjector, но я не уверен, как его использовать, как в ядре asp.net.Если есть способ заменить встроенный DI, как описано здесь Замена контейнера службы по умолчанию , и я знаю, что команда SI не рекомендует подход Руководство по интеграции ASP.NET Core MVC есть лучший способ в этом случае использования?

Вот то, что у меня есть, но это неудобно

- основная программа

internal class Program
{
    private static async Task Main(string[] args)
    {
        var isService = !(Debugger.IsAttached || args.Contains("--console"));

        var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Runner>();
                //configure SimpleInjector here???
            });

        if (isService)
        {
            await builder.RunAsServiceAsync();
        }
        else
        {
            await builder.RunConsoleAsync();
        }
    }
}

Настройка контейнера здесь работает большеили меньше, но первый класс, создаваемый хостом (то есть Runner в данном случае), создается хостом и внедряет любые зависимости через IServicesCollection.Поэтому мой вопрос: как мне вместо этого ввести его из моего контейнера SI?

Ответы [ 2 ]

0 голосов
/ 02 мая 2019

Я бы подключился к методу ConfigureContainer HostBuilder и установил туда simpleinjectore, например:

                   HostBuilder()
                   .ConfigureContainer<ServiceCollection>((builder, services) =>
                   {
                       var container = new Container();

                       container.RegisterSingleton<IJobRepository, JobRepository>();
                       services.AddTransient<IHostedService, TimedService>();

                   })
                   .ConfigureServices((hostContext, services) =>
                   {
                       // Originally we would have done this
                       //services.AddHostedService<Service>();
                   })
                   .Build();

        using (host)
        {
            await host.StartAsync();
            await host.WaitForShutdownAsync();
        }

Хотя вы действительно можете использовать реализацию IHostedService, я думаю, что она может скрыть то, что происходит.Я считаю, что начальную загрузку инфраструктуры следует проводить в одном месте или организовывать хотя бы в одном месте.Я считаю, что контейнер является инфраструктурой, и настроил бы все это вместе с остальным приложением с помощью методов HostBuilder.

Дополнительным преимуществом также может быть то, что вы не полностью заменяете ServiceCollection, поскольку он хорошо работает при выполнениидругие вещи, связанные с рамками.Пример некоторых вещей, которые я все еще делал бы с ServiceCollection:

                   HostBuilder()
                   .ConfigureServices((hostContext, services) =>
                   {
                       services.AddLogging();
                       services.AddOptions();
                   })

Это соответствует тому, что указано в документах simpleinjector о настройке контейнера с помощью ASP.NET Core:

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

То же самое должно применяться только к ядру .net и универсальному HostBuilder.

0 голосов
/ 20 сентября 2018

Очевидный ответ здесь: не вводите никаких зависимостей в Runner.Вместо этого Runner - это класс, представляющий точку входа в ваше приложение, поэтому я настраиваю там свой контейнер и удаляю его, когда Runner останавливается.Полный код для бегуна ...

public class Runner : IHostedService, IDisposable
{
    private Container _container;
    public Runner()
    {
        _container = new Container();
        _container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        Bootstrapper.Bootstrap(_container);
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _container.Dispose();
        _container = null;
    }
}
...