AutoFac and Log4Net - Registering and using

2020-07-25 10:53发布

问题:

I have been instructed on using AutoFac (instead of Castle Windsor) along side log4net and am lost on how to correctly use these technologies together.

Using the example on the autofac website I have the following LoggerModule

public class LoggingModule : Module
{
    private static void InjectLoggerProperties(object instance)
    {
        var instanceType = instance.GetType();

        // Get all the injectable properties to set.
        // If you wanted to ensure the properties were only UNSET properties,
        // here's where you'd do it.
        var properties = instanceType
          .GetProperties(BindingFlags.Public | BindingFlags.Instance)
          .Where(p => p.PropertyType == typeof(ILog) && p.CanWrite && p.GetIndexParameters().Length == 0);

        // Set the properties located.
        foreach (var propToSet in properties)
        {
            propToSet.SetValue(instance, LogManager.GetLogger(instanceType), null);
        }
    }

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

    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        // Handle constructor parameters.
        registration.Preparing += OnComponentPreparing;

        // Handle properties.
        registration.Activated += (sender, e) => InjectLoggerProperties(e.Instance);
    }
} 

And the following code that registers it

builder.RegisterModule(new LoggingModule());

Is this the correct method of integrating it?

And how do I use it in, say, an MVC controller?

回答1:

The log4net module is just like any other Autofac module - you register it (as you show) in the ContainerBuilder along with all your other registrations.

// EITHER
builder.RegisterModule<LoggingModule>();
// OR
builder.RegisterModule(new LoggingModule());

The documentation on the log4net module page explains how this can be used to inject ILog parameters into constructors or properties on your objects.

So, just like any other IoC structured class, to consume it, you'd add either a constructor or property to allow it to be injected.

public class SomeClassThatNeedsLogging
{
  private ILog _logger;
  public SomeClassThatNeedsLogging(ILog logger)
  {
    this._logger = logger;
  }
}

And, again, you can use constructor or property injection.

public class SomeClassThatNeedsLogging
{
  public ILog Logger { get; set; }
}

When you resolve your registered consumer, Autofac does the wireup.

var someClass = container.Resolve<SomeClassThatNeedsLogging>();
// someClass will have the ILog value populated.

For controllers, you're registering those with Autofac already, so all you need to do is add the constructor parameter or public writable property. The MVC integration does all the resolution, so there's nothing manual to do, no Resolve call or anything.

If it's still unclear, I'd recommend spending some time with the Autofac quick start guide and diving into the rest of the documentation.