2

如何配置 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;
  }
}
4

2 回答 2

3

您可以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依赖项移入构造函数。并将 替换ILoggerFactoryILogger依赖项,因为注入构造函数应该只存储其传入的依赖项(或者替换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);
});

或者,如果您ILogger在 Simple Injector 中注册了(或您的自定义日志抽象),您可以执行以下操作:

applicationBuilder.Use(async (context, next) => {
    var middleware = container.GetInstance<LogMiddleware>();
    await middleware.Invoke(context, next);
});
于 2016-08-14T12:53:50.593 回答
0

您的代码有两个问题。

  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());
        }
于 2016-08-13T02:26:03.747 回答