Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic factory with Common.Logging and Autofac?

I would like to inject ILog into my classes, not an ILoggerFactoryAdapter, but the ILoggerFactoryAdapter needs the name of the calling class (the class that wants to log something, so i can be properly categorized) so can Autofac somehow identify the class which are requesting the ILog and automaticly create the ILog from the factory?

like image 971
Carl Hörberg Avatar asked Jul 21 '09 13:07

Carl Hörberg


2 Answers

Bailey Ling came up with a great approach that doesn't use stack walking - see post here: http://groups.google.com/group/autofac/msg/704f926779cbe8b3

like image 165
Nicholas Blumhardt Avatar answered Oct 13 '22 13:10

Nicholas Blumhardt


I've tried to do this too, but I couldn't find a way to get access to the activation stack of autofac (without patching it) to get to the type that is to be injected with the logger instance.

Below is the "Works On My Machine" certified way (Autofac-1.4.3.536)

protected override void Load(ContainerBuilder builder)
        {
            const string loggerName = "Logger.Name";

            builder.
                Register((c, p) => LogManager.GetLogger(p.Named<string>(loggerName))).
                OnPreparing((c, p) =>
            {
                var stack = p.Context.GetActivationStack();
                var requestingType = "default";
                if (stack != null && stack.Length > 1) requestingType = stack[1].Description;
                var parameters = new List<Parameter>(p.Parameters) { new NamedParameter(loggerName, requestingType) };
                p.Parameters = parameters;

            }).
            FactoryScoped();
}

static class ContextExtensions
{
    public static Autofac.Service[] GetActivationStack(this Autofac.IContext context)
    {
        const string notSupportedMessage = "GetActivationStack not supported for this context.";

        var type = context.GetType();
        if (type.FullName != "Autofac.Context") throw new NotSupportedException(notSupportedMessage);

        var field = type.GetField("_componentResolutionStack", BindingFlags.Instance | BindingFlags.NonPublic);
        if (field == null) throw new NotSupportedException(notSupportedMessage);

        var activationStack = field.GetValue(context) as Stack<Autofac.Service>;
        if (activationStack == null) throw new NotSupportedException(notSupportedMessage);

        return activationStack.ToArray();
    }
}
like image 28
Remco Schoeman Avatar answered Oct 13 '22 12:10

Remco Schoeman