DotNET Console Generic Host - Dependency Injection with Scrutor

2022. 9. 6. 00:00DOTNET/Generic Host

반응형

Console 에서도 DotNet 의 DI 시스템을 사용할 수 있다. 

이번 시간에서 지난 시간에 이어서 Generic Host 를 통해 console app 에서 DI 시스템을 사용 하는 방법을 알아보겠다. 또한 Scrutor 를 이용하여 scan 방식으로 service 를 자동 등록하는 방법도 알아 보겠다. 

 

다음과 같이 Helloworld.cs 를 생성해 보자 

Helloworld.cs

namespace GenericHost;
public interface IHelloworld
{
    string Execute();
}
public class Helloworld : IHelloworld
{
    public string Execute() => $"{DateTime.Now} : Hello World!!";
}

 

Program.cs

using GenericHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    {
        services.AddHostedService<Worker>();
        services.AddTransient<IHelloworld, Helloworld>();
    })
    .Build();

host.Run();

추가

Woker.cs

using GenericHost;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public sealed class Worker : IHostedService
{
    private readonly ILogger _logger;
    private readonly IHelloworld _helloworld;

    public Worker(
        ILogger<Worker> logger,
        IHostApplicationLifetime appLifetime,
        IHelloworld helloworld)
    {
        _logger = logger;
        _helloworld = helloworld;
        appLifetime.ApplicationStarted.Register(OnStarted);
        appLifetime.ApplicationStopping.Register(OnStopping);
        appLifetime.ApplicationStopped.Register(OnStopped);
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("1. StartAsync has been called.");

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("4. StopAsync has been called.");

        return Task.CompletedTask;
    }

    private void OnStarted()
    {
        _logger.LogInformation("2. OnStarted has been called.");
        _logger.LogInformation($"2.1. {_helloworld.Execute()} ");
    }

    private void OnStopping()
    {
        _logger.LogInformation("3. OnStopping has been called.");
    }

    private void OnStopped()
    {
        _logger.LogInformation("5. OnStopped has been called.");
    }
}

 

 

 

이번에는 Scrutor 을 설치하고 scan 방식을 활용해 보자

 

1. Scrutor 설치

dotnet add package scrutor

 

2. 인터페이스 추가

InjectableServices/Injectables.cs

namespace GenericHost.InjectableServices;
public interface IInjectableService { }
public interface ITransientService : IInjectableService { }
public interface IScopedService : IInjectableService { }
public interface ISingletonService : IInjectableService { }

3. Program.cs 에 scan 추가 및 코드 수정

using GenericHost.InjectableServices;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    {
        services.AddHostedService<Worker>();
        //services.AddTransient<IHelloworld, Helloworld>();
        services.Scan(scan => scan
                            .FromAssemblyOf<ITransientService>()
                            .AddClasses(classes => classes.AssignableTo<ITransientService>())
                            .AsSelfWithInterfaces()
                            .WithTransientLifetime()
                            .AddClasses(classes => classes.AssignableTo<IScopedService>())
                            .AsSelfWithInterfaces()
                            .WithScopedLifetime()
                            .AddClasses(classes => classes.AssignableTo<ISingletonService>())
                            .AsSelfWithInterfaces()
                            .WithSingletonLifetime()
                            );
    })
    .Build();

host.Run();

 

4. Helloworld.cs 에 적용

using GenericHost.InjectableServices;

namespace GenericHost;
public interface IHelloworld : ITransientService // <-- 인터페이스 추가
{
    string Execute();
}
public class Helloworld : IHelloworld
{
    public string Execute() => $"{DateTime.Now} : Hello World!!";
}

IHelloworld 가 ITransientService 를 구현하도록 일종의 Filtering 기법을 사용하면된다.

이렇게 하면 자동으로 scan 하여 IHelloworld 를 구현한 Helloworld class 를 DI 에 등록한다. 

 

이와 같이 dotnet 의 대부분의 시스템은 각각의 project 에서 같은 방식으로 사용이 가능하다.

그래서 Generic Host 라는 이름을 붙인걸로 추정된다. 

 

관련영상

https://youtu.be/ocuKNxGJziU

 

반응형