log4net 集成中间件
尽管没有专门针对 log4net 的特定库,但你可以通过简单的中间件和一个小型自定义模块轻松注入 log4net.ILog
对象。Log4NetMiddleware
还是使用 管道中间件 的一个好例子。
以下是根据激活组件类型注入 ILog
参数的示例中间件。此中间件处理构造函数和属性注入。
public class Log4NetMiddleware : IResolveMiddleware
{
public PipelinePhase Phase => PipelinePhase.ParameterSelection;
public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
{
// 添加我们的参数。
context.ChangeParameters(context.Parameters.Union(
new[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof(ILog),
(p, i) => LogManager.GetLogger(p.Member.DeclaringType)
),
}));
// 继续解析。
next(context);
// 实例已被激活吗?
if (context.NewInstanceActivated)
{
var instanceType = context.Instance.GetType();
// 获取所有可注入的属性并设置。
// 如果你想确保这些属性只是未设置的属性,这里就是你实现的地方。
var properties = instanceType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(ILog) && p.CanWrite && p.GetIndexParameters().Length == 0);
// 设置找到的属性。
foreach (var propToSet in properties)
{
propToSet.SetValue(context.Instance, LogManager.GetLogger(instanceType), null);
}
}
}
}
性能提示:当前,调用 LogManager.GetLogger(type)
会带来轻微的性能影响,因为内部日志管理器会锁定日志器集合以获取合适的日志器。对于中间件的增强可以添加围绕日志实例的缓存,这样在 LogManager
调用中避免锁的开销。
接下来是一个简单的 MiddlewareModule
(不特定于日志),它为每个注册项添加一个单一的中间件实例到管道中。
// 为每个注册项添加一个中间件实例。
public class MiddlewareModule : Autofac.Module
{
private readonly IResolveMiddleware middleware;
public MiddlewareModule(IResolveMiddleware middleware)
{
this.middleware = middleware;
}
protected override void AttachToComponentRegistration(IComponentRegistryBuilder componentRegistryBuilder, IComponentRegistration registration)
{
// 附加到注册项的管道构建。
registration.PipelineBuilding += (sender, pipeline) =>
{
// 将我们的中间件添加到管道中。
pipeline.Use(middleware);
};
}
}