2

How can I configure SimpleInjector to resolve LogMiddleware's Invoke method dependency, like IMessageService ?

As I know, Asp.net core uses HttpContext.RequestServices (IServiceProvider) to resolve dependencies, I set SimpleInjector container to HttpContext.RequestServices property but didn't work. I want to change ServiceProvider dynamically because each tenant should have a container.

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;
  }
}
2
  • 1
    I don't understand exactly what your problem is. What prevents you from using your middleware? Commented Aug 12, 2016 at 19:05
  • How can I resolve middleware's dependencies from simple injector? Commented Aug 14, 2016 at 11:27

2 Answers 2

3

You can use your LogMiddleware class as follows:

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

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

I however advise you to change your middleware class a little bit. Move the runtime data (the next() delegate) out of the constructor (since components should not require runtime data during construction), and move the IMessageService dependency into the constructor. And replace the ILoggerFactory with a ILogger dependency, since an injection constructor should do no more than store its incoming dependencies (or replace ILogger with your own application-specific logger abstraction instead).

Your middleware class will then look as follows:

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();
    }
}

This allows you to use your middleware as follows:

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);
});

Or in case you registered the ILogger (or your custom logging abstraction) in Simple Injector, you can do the following:

applicationBuilder.Use(async (context, next) => {
    var middleware = container.GetInstance<LogMiddleware>();
    await middleware.Invoke(context, next);
});
Sign up to request clarification or add additional context in comments.

Comments

0

There is two problem with your code.

  1. Your "DefaultMessageService" does not implement interface "IMessageService". It should be like this.
 public class DefaultMessageService : IMessageService
 {
 public string Format(string message)
{
   return "Path:" + message;
 }
}
  1. You have to register DefaultMessageService in ConfigureService in Startup.cs.
 public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddMvc();
            services.AddSingleton<IMessageService>(new DefaultMessageService());
        }

1 Comment

sorry I forgot to write IMessageService when creating question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.