Stack Exchange
Why does Autofac fail to find log4net using the "LogInjectionModule"?
As discussed on the Autofac Wiki, the best way to automatically inject the log4net.ILog implementation for a class is to use the LogInjectionModule. This module's implementation is given in the wiki article:
public class LogInjectionModule : Module
{
    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        if (registration == null) throw new ArgumentNullException("registration");
        registration.Preparing += OnComponentPreparing;
    }

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

I'm including this module along with a module of my own to configure some components:
var builder = new ContainerBuilder();
builder.RegisterModule(new Common.Logging.LogInjectionModule());
builder.RegisterModule(new DataLayer.DataLayerModule("connectionstring"));
builder.RegisterType<SomeServiceType>();
AutofacHostFactory.Container = builder.Build();

Inside the DataLayerModule I'm constructing a type as follows:
protected override void Load(ContainerBuilder builder)
{
    builder.Register(c => new DataAccess(this.ConnectionString, c.Resolve<ILog>()))
        .As<IDataAccess>();

    // Some other type registrations...
}

When my application attempts to construct an IDataAccess object I get the following exception:

The requested service 'log4net.ILog' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

I know that on the wiki page it is mentioned that the injection method only works for constructor injection. However I thought that was what I was doing here. Am I wrong?

Edit
On further investigation, my original answer doesn't fix your problem (I've left it below for reference). The issue is that your code bypasses the LogInjectionModule by creating a new instance of DataAccess and resolving ILog directly. This is not a usage pattern that is supported by the LogInjectionModule, which is designed to provide an ILog instance that matches the type of the instance being activated by Autofac (log4net's LogManager.GetLogger() method needs to know about the type that is using the logger).
To work around this, you have two options. The simplest is to provide the logger instance directly without using the LogInjectionModule:
builder.Register(c => 
            new DataAccess(
                this.ConnectionString, 
                LogManager.GetLogger(typeof(DataAccess)))
       .As<IDataAccess>();

Alternatively (and more cleanly), you can register DataAccess in the normal Autofac way, and then register IDataAccess by using named parameters to specify the connection string that Autofac passes to the constructor. With this technique, you are enabling Autofac to use the LogInjectionModule when resolving the constructor's ILog parameter.
builder.RegisterType<DataAccess>();
builder.Register(c => 
            c.Resolve<DataAccess>(
               new NamedParameter("connectionString", this.ConnectionString)))
       .As<IDataAccess>();

(Note that this code assumes that the connection string parameter in the DataAccess constructor is named "connectionString").
The advantage of the second technique is that your module doesn't reference log4net's LogManager class directly, so the only coupling is to the ILog interface.

Original (incorrect) answer
That code sample is for Autofac v2.0 (I originally provided the sample on that wiki page). The code for my current working module (for Autofac v2.4.5) is:
public class LogInjectionModule : ComponentInjectionModule
{
    /// <summary>
    ///     Called when Autofac is preparing a component for activation.
    /// </summary>
    /// <param name = "sender">
    ///     The sender.
    /// </param>
    /// <param name = "e">
    ///     The <see cref = "ActivatingEventArgs{T}" /> instance containing the event data.
    /// </param>
    protected override void OnComponentPreparing(object sender, PreparingEventArgs e)
    {
        Enforce.ArgumentNotNull(e, "e");

        Type t = e.Component.Activator.LimitType;
        e.Parameters = e.Parameters.Union(
            new[]
                {
                    new ResolvedParameter(
                        (p, i) => p.ParameterType == typeof(ILog), (p, i) => LogManager.GetLogger(t))
                });
    }
}

That code relies on my ComponentInjectionModule class which is defined below. There are some subtle differences in the way that this module hooks into the registration/activation process.
/// <summary>
///     Base module for injecting into registrations when they are prepared/activated.
/// </summary>
public class ComponentInjectionModule : IModule
{
    /// <summary>
    ///     Apply the module to the component registry.
    /// </summary>
    /// <param name = "componentRegistry">
    ///     Component registry to apply configuration to.
    /// </param>
    public void Configure(IComponentRegistry componentRegistry)
    {
        Enforce.ArgumentNotNull(componentRegistry, "componentRegistry");

        foreach (var registration in componentRegistry.Registrations)
        {
            this.AttachToComponentRegistration(registration);
        }

        componentRegistry.Registered +=
            (sender, e) => this.AttachToComponentRegistration(e.ComponentRegistration);
    }

    /// <summary>
    ///     Attaches to the <see cref = "IComponentRegistration.Preparing" /> event of a component registration.
    /// </summary>
    /// <param name = "registration">
    ///     The registration whose Preparing event will be attached.
    /// </param>
    protected virtual void AttachToComponentRegistration(IComponentRegistration registration)
    {
        Enforce.ArgumentNotNull(registration, "registration");

        registration.Preparing += this.OnComponentPreparing;
        registration.Activating += this.OnComponentActivating;
        registration.Activated += this.OnComponentActivated;
    }

    /// <summary>
    /// Called when Autofac has activated a component.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="ActivatedEventArgs{T}"/> instance containing the event data.</param>
    [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", Justification = "Not an event handler")]
    protected virtual void OnComponentActivated(object sender, ActivatedEventArgs<object> e)
    {
    }

    /// <summary>
    /// Called when Autofac is activating a component.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="ActivatingEventArgs{T}"/> instance containing the event data.</param>
    [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", Justification = "Not an event handler")]
    protected virtual void OnComponentActivating(object sender, ActivatingEventArgs<object> e)
    {
    }

    /// <summary>
    /// Called when Autofac is preparing a component for activation.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="ActivatingEventArgs{T}"/> instance containing the event data.</param>
    [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", Justification = "Not an event handler")]
    protected virtual void OnComponentPreparing(object sender, PreparingEventArgs e)
    {
    }
}


Thanks for the comprehensive answer! I figured that I'd misunderstood how the LogInjectionModule worked. Went with the "cleaner" option you gave and it works a treat.
