다음을 통해 공유


System.CommandLine에서 종속성 주입을 구성하는 방법

Important

System.CommandLine은 현재 미리 보기로 제공되며 이 설명서는 버전 2.0 베타 4용입니다. 일부 정보는 릴리스되기 전에 상당 부분 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.

사용자 지정 바인더를 사용하여 명령 처리기에 사용자 지정 형식을 삽입합니다.

다음과 같은 이유로 처리기별 DI(종속성 주입)를 사용하는 것이 좋습니다.

  • 명령줄 앱은 시작 비용이 성능에 눈에 띄는 영향을 미칠 수 있는 단기 프로세스인 경우가 많습니다. 성능 최적화는 탭 완료를 계산해야 하는 경우 특히 중요합니다. 명령줄 앱은 비교적 수명이 긴 프로세스인 웹 및 GUI 앱과는 다릅니다. 불필요한 시작 시간은 단기 프로세스에는 적합하지 않습니다.
  • 여러 하위 명령이 있는 명령줄 앱이 실행되면 해당 하위 명령 중 하나만 실행됩니다. 앱이 실행되지 않는 하위 명령에 대한 종속성을 구성하면 불필요하게 성능이 저하됩니다.

DI를 구성하려면 BinderBase<T>에서 파생되는 클래스를 만듭니다. 여기에서 T는 인스턴스를 삽입하려는 인터페이스입니다. GetBoundValue 메서드 재정의에서 삽입하려는 인스턴스를 가져와 반환합니다. 다음 예제에서는 ILogger의 기본 로거 구현을 삽입합니다.

public class MyCustomBinder : BinderBase<ILogger>
{
    protected override ILogger GetBoundValue(
        BindingContext bindingContext) => GetLogger(bindingContext);

    ILogger GetLogger(BindingContext bindingContext)
    {
        using ILoggerFactory loggerFactory = LoggerFactory.Create(
            builder => builder.AddConsole());
        ILogger logger = loggerFactory.CreateLogger("LoggerCategory");
        return logger;
    }
}

SetHandler 메서드를 호출할 때 삽입된 클래스의 인스턴스를 람다에 전달하고 서비스 목록에 있는 바인더 클래스의 인스턴스를 전달합니다.

rootCommand.SetHandler(async (fileOptionValue, logger) =>
    {
        await DoRootCommand(fileOptionValue!, logger);
    },
    fileOption, new MyCustomBinder());

다음 코드는 앞의 예제를 포함하는 전체 프로그램입니다.

using System.CommandLine;
using System.CommandLine.Binding;
using Microsoft.Extensions.Logging;

class Program
{
    static async Task Main(string[] args)
    {
        var fileOption = new Option<FileInfo?>(
              name: "--file",
              description: "An option whose argument is parsed as a FileInfo");

        var rootCommand = new RootCommand("Dependency Injection sample");
        rootCommand.Add(fileOption);

        rootCommand.SetHandler(async (fileOptionValue, logger) =>
            {
                await DoRootCommand(fileOptionValue!, logger);
            },
            fileOption, new MyCustomBinder());

        await rootCommand.InvokeAsync("--file scl.runtimeconfig.json");
    }

    public static async Task DoRootCommand(FileInfo aFile, ILogger logger)
    {
        Console.WriteLine($"File = {aFile?.FullName}");
        logger.LogCritical("Test message");
        await Task.Delay(1000);
    }

    public class MyCustomBinder : BinderBase<ILogger>
    {
        protected override ILogger GetBoundValue(
            BindingContext bindingContext) => GetLogger(bindingContext);

        ILogger GetLogger(BindingContext bindingContext)
        {
            using ILoggerFactory loggerFactory = LoggerFactory.Create(
                builder => builder.AddConsole());
            ILogger logger = loggerFactory.CreateLogger("LoggerCategory");
            return logger;
        }
    }
}

참고 항목

System.CommandLine 개요