ASP.NET Core에서 타사 컨테이너를 사용한 미들웨어 활성화

이 문서에서는 IMiddlewareFactoryIMiddleware를 타사 컨테이너를 사용한 미들웨어 활성화를 위한 확장 지점으로 사용하는 방법을 보여 줍니다. IMiddlewareFactoryIMiddleware에 대한 소개 정보는 ASP.NET Core의 팩터리 기반 미들웨어 활성화를 참조하세요.

샘플 코드 보기 및 다운로드(다운로드 방법)

샘플 앱은 IMiddlewareFactory 구현 SimpleInjectorMiddlewareFactory를 사용한 미들웨어 활성화를 보여 줍니다. 이 샘플에서는 간단한 인젝터 DI(종속성 주입) 컨테이너를 사용합니다.

이 샘플의 미들웨어 구현은 쿼리 문자열 매개 변수(key)에서 제공한 값을 기록합니다. 이 미들웨어는 주입된 데이터베이스 컨텍스트(범위가 지정된 서비스)를 사용하여 메모리 내 데이터베이스에 쿼리 문자열 값을 기록합니다.

참고 항목

이 샘플 앱에서는 순전히 예시 목적으로 간단한 인젝터를 사용합니다. 간단한 인젝터의 사용은 보증하지 않습니다. 간단한 인젝터 설명서 및 GitHub 문제에 설명된 미들웨어 활성화 방법은 간단한 인젝터의 관리자에서 권장됩니다. 자세한 내용은 간단한 인젝터 설명서간단한 인젝터 GitHub 리포지토리를 참조하세요.

IMiddlewareFactory

IMiddlewareFactory는 미들웨어를 만드는 메서드를 제공합니다.

샘플 앱에서는 미들웨어 팩터리를 구현하여 SimpleInjectorActivatedMiddleware 인스턴스를 만듭니다. 미들웨어 팩터리는 간단한 인젝터 컨테이너를 사용하여 미들웨어를 해결합니다.

public class SimpleInjectorMiddlewareFactory : IMiddlewareFactory
{
    private readonly Container _container;

    public SimpleInjectorMiddlewareFactory(Container container)
    {
        _container = container;
    }

    public IMiddleware Create(Type middlewareType)
    {
        return _container.GetInstance(middlewareType) as IMiddleware;
    }

    public void Release(IMiddleware middleware)
    {
        // The container is responsible for releasing resources.
    }
}

IMiddleware

IMiddleware는 앱의 요청 파이프라인에 대한 미들웨어를 정의합니다.

IMiddlewareFactory 구현(Middleware/SimpleInjectorActivatedMiddleware.cs)에 의해 활성화된 미들웨어:

public class SimpleInjectorActivatedMiddleware : IMiddleware
{
    private readonly AppDbContext _db;

    public SimpleInjectorActivatedMiddleware(AppDbContext db)
    {
        _db = db;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var keyValue = context.Request.Query["key"];

        if (!string.IsNullOrWhiteSpace(keyValue))
        {
            _db.Add(new Request()
                {
                    DT = DateTime.UtcNow, 
                    MiddlewareActivation = "SimpleInjectorActivatedMiddleware", 
                    Value = keyValue
                });

            await _db.SaveChangesAsync();
        }

        await next(context);
    }
}

미들웨어Middleware/MiddlewareExtensions.cs()에 대한 확장이 만들어집니다.

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseSimpleInjectorActivatedMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<SimpleInjectorActivatedMiddleware>();
    }
}

Startup.ConfigureServices는 여러 작업을 수행해야 합니다.

  • 간단한 인젝터 컨테이너를 설정합니다.
  • 팩터리와 미들웨어를 등록합니다.
  • 간단한 인젝터 컨테이너에서 앱의 데이터베이스 컨텍스트를 사용할 수 있게 만듭니다.
public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    // Replace the default middleware factory with the 
    // SimpleInjectorMiddlewareFactory.
    services.AddTransient<IMiddlewareFactory>(_ =>
    {
        return new SimpleInjectorMiddlewareFactory(_container);
    });

    // Wrap ASP.NET Core requests in a Simple Injector execution 
    // context.
    services.UseSimpleInjectorAspNetRequestScoping(_container);

    // Provide the database context from the Simple 
    // Injector container whenever it's requested from 
    // the default service container.
    services.AddScoped<AppDbContext>(provider => 
        _container.GetInstance<AppDbContext>());

    _container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

    _container.Register<AppDbContext>(() => 
    {
        var optionsBuilder = new DbContextOptionsBuilder<DbContext>();
        optionsBuilder.UseInMemoryDatabase("InMemoryDb");
        return new AppDbContext(optionsBuilder.Options);
    }, Lifestyle.Scoped);

    _container.Register<SimpleInjectorActivatedMiddleware>();

    _container.Verify();
}

미들웨어는 Startup.Configure의 요청 처리 파이프라인에 등록됩니다.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseSimpleInjectorActivatedMiddleware();

    app.UseStaticFiles();
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

이 문서에서는 IMiddlewareFactoryIMiddleware를 타사 컨테이너를 사용한 미들웨어 활성화를 위한 확장 지점으로 사용하는 방법을 보여 줍니다. IMiddlewareFactoryIMiddleware에 대한 소개 정보는 ASP.NET Core의 팩터리 기반 미들웨어 활성화를 참조하세요.

샘플 코드 보기 및 다운로드(다운로드 방법)

샘플 앱은 IMiddlewareFactory 구현 SimpleInjectorMiddlewareFactory를 사용한 미들웨어 활성화를 보여 줍니다. 이 샘플에서는 간단한 인젝터 DI(종속성 주입) 컨테이너를 사용합니다.

이 샘플의 미들웨어 구현은 쿼리 문자열 매개 변수(key)에서 제공한 값을 기록합니다. 이 미들웨어는 주입된 데이터베이스 컨텍스트(범위가 지정된 서비스)를 사용하여 메모리 내 데이터베이스에 쿼리 문자열 값을 기록합니다.

참고 항목

이 샘플 앱에서는 순전히 예시 목적으로 간단한 인젝터를 사용합니다. 간단한 인젝터의 사용은 보증하지 않습니다. 간단한 인젝터 설명서 및 GitHub 문제에 설명된 미들웨어 활성화 방법은 간단한 인젝터의 관리자에서 권장됩니다. 자세한 내용은 간단한 인젝터 설명서간단한 인젝터 GitHub 리포지토리를 참조하세요.

IMiddlewareFactory

IMiddlewareFactory는 미들웨어를 만드는 메서드를 제공합니다.

샘플 앱에서는 미들웨어 팩터리를 구현하여 SimpleInjectorActivatedMiddleware 인스턴스를 만듭니다. 미들웨어 팩터리는 간단한 인젝터 컨테이너를 사용하여 미들웨어를 해결합니다.

public class SimpleInjectorMiddlewareFactory : IMiddlewareFactory
{
    private readonly Container _container;

    public SimpleInjectorMiddlewareFactory(Container container)
    {
        _container = container;
    }

    public IMiddleware Create(Type middlewareType)
    {
        return _container.GetInstance(middlewareType) as IMiddleware;
    }

    public void Release(IMiddleware middleware)
    {
        // The container is responsible for releasing resources.
    }
}

IMiddleware

IMiddleware는 앱의 요청 파이프라인에 대한 미들웨어를 정의합니다.

IMiddlewareFactory 구현(Middleware/SimpleInjectorActivatedMiddleware.cs)에 의해 활성화된 미들웨어:

public class SimpleInjectorActivatedMiddleware : IMiddleware
{
    private readonly AppDbContext _db;

    public SimpleInjectorActivatedMiddleware(AppDbContext db)
    {
        _db = db;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var keyValue = context.Request.Query["key"];

        if (!string.IsNullOrWhiteSpace(keyValue))
        {
            _db.Add(new Request()
                {
                    DT = DateTime.UtcNow, 
                    MiddlewareActivation = "SimpleInjectorActivatedMiddleware", 
                    Value = keyValue
                });

            await _db.SaveChangesAsync();
        }

        await next(context);
    }
}

미들웨어Middleware/MiddlewareExtensions.cs()에 대한 확장이 만들어집니다.

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseSimpleInjectorActivatedMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<SimpleInjectorActivatedMiddleware>();
    }
}

Startup.ConfigureServices는 여러 작업을 수행해야 합니다.

  • 간단한 인젝터 컨테이너를 설정합니다.
  • 팩터리와 미들웨어를 등록합니다.
  • 간단한 인젝터 컨테이너에서 앱의 데이터베이스 컨텍스트를 사용할 수 있게 만듭니다.
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    // Replace the default middleware factory with the 
    // SimpleInjectorMiddlewareFactory.
    services.AddTransient<IMiddlewareFactory>(_ =>
    {
        return new SimpleInjectorMiddlewareFactory(_container);
    });

    // Wrap ASP.NET Core requests in a Simple Injector execution 
    // context.
    services.UseSimpleInjectorAspNetRequestScoping(_container);

    // Provide the database context from the Simple 
    // Injector container whenever it's requested from 
    // the default service container.
    services.AddScoped<AppDbContext>(provider => 
        _container.GetInstance<AppDbContext>());

    _container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

    _container.Register<AppDbContext>(() => 
    {
        var optionsBuilder = new DbContextOptionsBuilder<DbContext>();
        optionsBuilder.UseInMemoryDatabase("InMemoryDb");
        return new AppDbContext(optionsBuilder.Options);
    }, Lifestyle.Scoped);

    _container.Register<SimpleInjectorActivatedMiddleware>();

    _container.Verify();
}

미들웨어는 Startup.Configure의 요청 처리 파이프라인에 등록됩니다.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseSimpleInjectorActivatedMiddleware();

    app.UseStaticFiles();
    app.UseMvc();
}

추가 리소스