So I'm following an example of setting up LoggerMiddleware which is demonstrated here which I've adapted to just use .NET Core's ILogger. We already had a LoggerModule which work pre v6 so I copied the creation code into the LoggerMiddleware class to suit.
What I don't understand is how to register this. There's no default constructor on the Module so I can't use builder.RegisterModule<MiddlewareModule>(). I know I can pre-create the MiddlewareModule passing in an instance of the LoggerMiddleware then builder.RegisterModule(moduleInstance) but this MiddlewareModule is supposed to be used for all Middleware we create. This doco page doesn't elaborate on that final detail. Do I just do this per instance of IResolveMiddleware?:
var loggerMiddlewareModule = new MiddlewareModule(new LoggerMiddleware());
builder.RegisterModule(loggerMiddlewareModule);
var otherMiddlewareModule = new MiddlewareModule(new OtherMiddleware());
builder.RegisterModule(otherMiddlewareModule);
My Middleware and Module:
public class LoggerMiddleware : IResolveMiddleware
{
public PipelinePhase Phase => PipelinePhase.ParameterSelection;
public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
{
var t = context.Registration.Activator.LimitType;
// Add our parameters.
context.ChangeParameters(context.Parameters.Union(
new[]
{
new ResolvedParameter((p, i) => p.ParameterType == typeof(ILogger), (p, i) => GetLogger(i, t)),
new ResolvedParameter(
(p, i) => p.ParameterType.GenericTypeArguments.Any() &&
p.ParameterType.GetGenericTypeDefinition() == typeof(ILogger<>),
(p, i) => GetGenericTypeLogger(i, t))
}));
// Continue the resolve.
next(context);
// Has an instance been activated?
if (context.NewInstanceActivated)
{
var instanceType = context.Instance.GetType();
// Get all the injectable properties to set.
// If you wanted to ensure the properties were only UNSET properties,
// here's where you'd do it.
var properties = instanceType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(ILogger) && p.CanWrite && p.GetIndexParameters().Length == 0);
// Set the properties located.
foreach (var propToSet in properties)
{
propToSet.SetValue(context.Instance, GetLogger(context, instanceType), null);
}
}
}
/// <summary>
/// The log cache.
/// </summary>
private static readonly ConcurrentDictionary<Type, object> _logCache = new ConcurrentDictionary<Type, object>();
/// <summary>
/// Gets the logger.
/// </summary>
/// <param name="context">The component context.</param>
/// <param name="declaringType">The type of logger.</param>
/// <returns>The logger instance.</returns>
private static object GetGenericTypeLogger(IComponentContext context, Type declaringType)
{
return _logCache.GetOrAdd(
declaringType,
x =>
{
var wrapper = typeof(LoggerWrapper<>);
var specificWrapper = wrapper.MakeGenericType(declaringType);
var instance = (ILoggerWrapper)Activator.CreateInstance(specificWrapper);
var factory = context.Resolve<ILoggerFactory>();
return instance!.Create(factory);
});
}
/// <summary>
/// Gets the logger.
/// </summary>
/// <param name="context">The component context.</param>
/// <param name="declaringType">The type of logger.</param>
/// <returns>The logger instance.</returns>
private static object GetLogger(IComponentContext context, Type declaringType)
{
return _logCache.GetOrAdd(
declaringType,
x =>
{
var factory = context.Resolve<ILoggerFactory>();
return factory.CreateLogger(declaringType);
});
}
/// <summary>
/// The <see cref="ILoggerWrapper" />
/// interface defines the method for creating a generic type logger.
/// </summary>
private interface ILoggerWrapper
{
/// <summary>
/// Creates a generic type logger using the specified factory.
/// </summary>
/// <param name="factory">The factory.</param>
/// <returns>The logger.</returns>
object Create(ILoggerFactory factory);
}
private class LoggerWrapper<T> : ILoggerWrapper
{
public object Create(ILoggerFactory factory)
{
return factory.CreateLogger<T>();
}
}
}
public class MiddlewareModule : Module
{
private readonly IResolveMiddleware _middleware;
public MiddlewareModule(IResolveMiddleware middleware)
{
_middleware = middleware;
}
protected override void AttachToComponentRegistration(IComponentRegistryBuilder componentRegistry, IComponentRegistration registration)
{
// Attach to the registrations pipeline build
registration.PipelineBuilding += (sender, pipeline) =>
{
// Add our middleware to the pipeline
pipeline.Use(_middleware);
};
}
===============
Further question:
So when I run this I'm getting DependencyResolutionException and not quite sure where to look.
This is what the middleware module registration looks like:

There are other standard modules doing RegisterType and Register calls.
