【问题标题】:IAutofacActionFilter injecting a loggerIAutofacActionFilter 注入记录器
【发布时间】:2015-05-06 19:48:16
【问题描述】:

我在这个模块中使用 NLog:

public class LoggingModule : Autofac.Module
{
    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        registration.Preparing += OnComponentPreparing;
        registration.Activated += (sender, e) => InjectLoggerProperties(e.Instance);
    }

    private static void OnComponentPreparing(object sender, PreparingEventArgs e)
    {
        var t = e.Component.Activator.LimitType;
        e.Parameters = e.Parameters.Union(
            new[]
            {
                new ResolvedParameter((p, i) => IsLogger(p), (p, i) => GetLogger(t.FullName))
            });
    }

    private static void InjectLoggerProperties(object instance)
    {
        var instanceType = instance.GetType();

        var properties = instanceType
            .GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Where(p => IsLogger(p) && p.CanWrite && p.GetIndexParameters().Length == 0);

        foreach (var propToSet in properties)
        {
            propToSet.SetValue(instance, GetLogger(instanceType.FullName), null);
        }
    }

    private static ILogger GetLogger(string name)
    {
        return LogManager.GetLogger(name);
    }

    private static bool IsLogger(ParameterInfo p)
    {
        return p.ParameterType == typeof (ILogger);
    }

    private static bool IsLogger(PropertyInfo p)
    {
        return p.PropertyType == typeof(ILogger);
    }
}

一切似乎都很好,除了记录器的名称是空的/错误的。在OnComponentPreparing 的第一行,LimitTypeMeta<Lazy<IAutofacActionFilter>>[],而不是预期的LogControllerActionFilterAttribute。如何获得记录器的正确类型名称?在我的日志中,这是作为记录器名称给出的:

0,文化=中性,PublicKeyToken=b77a5c561934e089]][]

编辑:

这是一个演示此问题的简短而完整的程序。您还需要上面的模块实现。

internal class Program
{
    private static void Main(string[] args)
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule<LoggingModule>();
        builder.RegisterType<Foo>().As<IFoo>();

        var container = builder.Build();

        // This prints out "0, Culture=neutral, PublicKeyToken=b77a5c561934e089]][]" for the logger name
        foreach (var metalazyfoo in container.Resolve<Meta<Lazy<IFoo>>[]>())
            metalazyfoo.Value.Value.Work(5);

        // This prints out "Foo" for the logger name
        container.Resolve<Meta<Lazy<IFoo>>>().Value.Value.Work(6);

        Console.WriteLine("=== Done ===");
        Console.ReadLine();
    }
}


public class Foo : IFoo
{
    private readonly Logger _logger;

    public Foo(Logger logger)
    {
        _logger = logger;
    }

    public void Work(int x)
    {
        _logger.Debug(x);
    }
}

public interface IFoo
{
    void Work(int x);
}

【问题讨论】:

  • 我正在尝试复制您的配置,但我不知道您从哪里获得 NLogAdapter。你用的是什么包。我在一个项目中使用官方适配器(github.com/ziyasal/Autofac.Extras.NLog),它工作正常。
  • NLogAdapter 是我们围绕特定日志实现的包装类之一。它只是从 NLog 中包装了 Logger,所以我们的大部分代码都没有依赖于 NLog。我将研究 autofac 模块,看看它的代码有何不同。
  • 是的,看一下,你只需要注册模块就完成了:-)
  • 我们无法使用该模块。它会在每个使用它的项目中创建对 Autofac 和 NLog 的依赖,这是我们试图避免的。
  • 嗯,确实如此,但最终您将在项目周围注入 ILogger 接口,这将调用方法 _logger.Log(....)。依赖关系的问题主要是您在切换到另一个 IOC 容器/记录器时必须付出的努力。在这种特殊情况下,工作量将非常低,因为您可能会有另一个 ILogger 界面,所以我认为这不是悲剧:-)

标签: c# asp.net-web-api2 autofac nlog autofac-module


【解决方案1】:

这里的LimitType应该是

var t = e.Component.Target.Activator.LimitType;

代替

var t = e.Component.Activator.LimitType;

这是为了避免使用激活器的类型创建记录器,而不是被激活的底层组件的类型。这就是为什么你得到 Meta>[] 而不是 LogControllerActionFilterAttribute。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多