views:

484

answers:

2

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?

+2  A: 

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();
    }
}
Remco Schoeman
wow, thanks, will try it out immediately!
Carl Hörberg
works like charm! Thank you!
Carl Hörberg
+7  A: 

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

Nicholas Blumhardt
Bailey's solution is great, but it doesn't work with the WebForms integration. The pages and user controls aren't registered, so the event handler never fires. There's a comment on the Autofac project site's wiki to the same effect (http://code.google.com/p/autofac/wiki/Log4NetIntegration).
David Rubin