项目
版本

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);
        };
    }
}
在本文档中