簡體   English   中英

配置簡單注入器以支持解決ASP.NET Core中間件依賴關系?

[英]Configure Simple Injector to support resolving ASP.NET Core middleware dependencies?

如何配置SimpleInjector來解決LogMiddleware的Invoke方法依賴關系,例如IMessageService?

據我所知,Asp.net核心使用HttpContext.RequestServices(IServiceProvider)來解決依賴關系,我將SimpleInjector容器設置為HttpContext.RequestServices屬性,但是沒有用。 我想動態更改ServiceProvider,因為每個租戶都應該有一個容器。

public class LogMiddleware
{
    RequestDelegate next;
    private readonly ILogger log;

    public LogMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
    {
        this.next = next;
        this.log = loggerFactory.CreateLogger<LogMiddleware>();
    }

    public async Task Invoke(HttpContext context, IMessageService messageService)
    {
         await context.Response.WriteAsync(
                messageService.Format(context.Request.Host.Value));
    }
}

public interface IMessageService
{
    string Format(string message);
}

public class DefaultMessageService : IMessageService
{
  public string Format(string message)
  {
    return "Path:" + message;
  }
}

您可以如下使用LogMiddleware類:

applicationBuilder.Use(async (context, next) => {
    var middleware = new LogMiddleware(
        request => next(),
        applicationBuilder.ApplicationServices.GetService<ILoggerFactory>());

    await middleware.Invoke(context, container.GetInstance<IMessageService>());
});

但是,我建議您稍微更改一下中間件類。 將運行時數據( next()委托)移出構造函數(因為在構造過程中組件不需要運行時數據 ),然后將IMessageService依賴項移入構造函數。 並將ILoggerFactory替換為ILogger依賴項,因為注入構造函數只需要存儲其傳入的依賴項即可 (或將ILogger替換為您自己的特定於應用程序的記錄器抽象 )。

您的中間件類將如下所示:

public sealed class LogMiddleware
{
    private readonly IMessageService messageService;
    private readonly ILogger log;

    public LogMiddleware(IMessageService messageService, ILogger log) {
        this.messageService = messageService;
        this.log = log;
    }

    public async Task Invoke(HttpContext context, Func<Task> next) {
        await context.Response.WriteAsync(
            messageService.Format(context.Request.Host.Value));

        await next();
    }
}

這使您可以如下使用中間件:

var factory = applicationBuilder.ApplicationServices.GetService<ILoggerFactory>();

applicationBuilder.Use(async (context, next) => {
    var middleware = new LogMiddleware(
        container.GetInstance<IMessageService>(),
        factory.CreateLogger<LogMiddleware>());

    await middleware.Invoke(context, next);
});

或者,如果您在Simple Injector中注冊了ILogger (或您的自定義日志記錄抽象),則可以執行以下操作:

applicationBuilder.Use(async (context, next) => {
    var middleware = container.GetInstance<LogMiddleware>();
    await middleware.Invoke(context, next);
});

您的代碼有兩個問題。

  1. 您的“ DefaultMessageService”未實現接口“ IMessageService”。 應該是這樣
  public class DefaultMessageService : IMessageService { public string Format(string message) { return "Path:" + message; } } 
  1. 您必須在Startup.cs的ConfigureService中注冊DefaultMessageService。
  public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc(); services.AddSingleton<IMessageService>(new DefaultMessageService()); } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM