1

I'm using NLog with this module:

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

Everything seems to work fine, except the logger's name is empty/wrong. On the first line of OnComponentPreparing, the LimitType is a Meta<Lazy<IAutofacActionFilter>>[] instead of the expected LogControllerActionFilterAttribute. How do I get the correct type name for the logger? In my logs, this is given as the logger name:

0, Culture=neutral, PublicKeyToken=b77a5c561934e089]][]

Edit:

This is a short and complete program demonstrating this issue. You'll need the module implementation above as well.

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);
}
  • I'm trying to replicate your configuration but I don't know where did you get NLogAdapter from. What packages are you using. I'm using the official adapter (https://github.com/ziyasal/Autofac.Extras.NLog) in a project and it's working fine. – Paolo Costa May 06 '15 at 20:09
  • The NLogAdapter is one of our wrapper classes around the specific logging implementations. It just wraps the Logger from NLog so the majority of our code has no dependency on NLog. I'll look into the autofac module and see how its code is different. –  May 06 '15 at 20:19
  • Yes, give a look at it, you just need to register the module and you are done :-) – Paolo Costa May 06 '15 at 20:25
  • We can't use the module. It creates a dependency on both Autofac and NLog in every project that uses it, which we're trying to avoid. –  May 06 '15 at 20:27
  • Well, that's true, but at the end of the day you will inject around your project an ILogger interface and this will call a method _logger.Log(....). The problem with dependencies is mainly the effort you have to put in place when it's time to switch to another IOC container / Logger. In this particular case the effort will be very low as you will probably have another ILogger interface, so I think it's not a tragedy :-) – Paolo Costa May 06 '15 at 21:04
  • Right now if we need to change away from Autofac, we have to change one project, not 20. Same thing with NLog. The logging interface provided by the module is specific to NLog and would require changes in every component in every project. That is untenable. Now, about my issue... –  May 06 '15 at 21:11
  • I'm not able to reproduce your issue. You can have a look to the used code sample here : https://dotnetfiddle.net/6hQ9Hk – Cyril Durand May 07 '15 at 09:03
  • The fiddle just gives me "Fatal Error: Memory usage limit was exceeded" –  May 07 '15 at 16:12
  • @Amy quite strange, I have the same message now. Could you try running the code on your local computer and tell me if you reproduce the issue with this code ? – Cyril Durand May 08 '15 at 00:14
  • Yes, I will do that later this afternoon. –  May 08 '15 at 15:57
  • @Amy did you test the code sample ? – Cyril Durand May 14 '15 at 11:17

1 Answers1

1

Here LimitType should be

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

Instead of

var t = e.Component.Activator.LimitType;

This is to avoid creating loggers with the type of the activator, not the type of the underlying component being activated. Which is why you're getting the Meta>[] instead of LogControllerActionFilterAttribute.

vendettamit
  • 14,315
  • 2
  • 32
  • 54