Изменить
При дальнейшем расследовании мой первоначальный ответ не решает вашу проблему (я оставил его ниже для справки). Проблема в том, что ваш код обходит LogInjectionModule, создавая new экземпляр DataAccess и напрямую разрешая ILog. Это не шаблон использования, поддерживаемый LogInjectionModule, который предназначен для предоставления экземпляра ILog, соответствующего типу экземпляра, активируемого Autofac (метод LogManager.GetLogger() log4net должен знать о типе, который использует регистратор).
Чтобы обойти это, у вас есть два варианта. Самый простой — предоставить экземпляр регистратора напрямую, без использования LogInjectionModule:
builder.Register(c =>
new DataAccess(
this.ConnectionString,
LogManager.GetLogger(typeof(DataAccess)))
.As<IDataAccess>();
В качестве альтернативы (и более аккуратно) вы можете зарегистрировать DataAccess обычным способом Autofac, а затем зарегистрировать IDataAccess с помощью именованные параметры для указания строки подключения, которую Autofac передает конструктору. С помощью этого метода вы позволяете Autofac использовать LogInjectionModule при разрешении параметра ILog конструктора.
builder.RegisterType<DataAccess>();
builder.Register(c =>
c.Resolve<DataAccess>(
new NamedParameter("connectionString", this.ConnectionString)))
.As<IDataAccess>();
(Обратите внимание, что в этом коде предполагается, что параметр строки подключения в конструкторе DataAccess имеет имя «connectionString»).
Преимущество второго метода заключается в том, что ваш модуль не ссылается напрямую на класс LogManager log4net, поэтому единственная связь - с интерфейсом ILog.
Исходный (неправильный) ответ
Этот пример кода предназначен для Autofac v2.0 (первоначально я предоставил образец на этой вики-странице). Код моего текущего рабочего модуля (для Autofac v2.4.5):
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))
});
}
}
Этот код основан на моем классе ComponentInjectionModule, который определен ниже. Есть некоторые тонкие различия в том, как этот модуль подключается к процессу регистрации/активации.
/// <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)
{
}
}
person
Rich Tebb
schedule
03.11.2011