使用Log Injection Module时,在Autofac中显式解析ILog

Bor*_*sky 4 .net c# log4net dependency-injection autofac

我使用以下代码为所有需要它的类注册log4net.

public class LogInjectionModule : Module
{
    private readonly string _configPath;

    public LogInjectionModule(string configPath)
    {
        _configPath = configPath;
    }

    protected override void AttachToComponentRegistration(IComponentRegistry registry,
        IComponentRegistration registration)
    {
        XmlConfigurator.Configure(new FileInfo(_configPath));

        registration.Preparing += OnComponentPreparing;
    }

    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))
                                          });
    }
}
Run Code Online (Sandbox Code Playgroud)

使用autofac的类型扫描注册所有类:

builder.RegisterAssemblyTypes(typeof (IResourceFinder).Assembly)
 .AsImplementedInterfaces();
Run Code Online (Sandbox Code Playgroud)

它工作正常!

需要明确注册一个类尝试解决ILog并失败

builder.Register(x => new ClassThatNeedsILog(x.Resolve<ILog>())).AsImplementedInterfaces();
Run Code Online (Sandbox Code Playgroud)

这是上课

public class ClassThatNeedsILog
{
    public ClassThatNeedsILog(ILog log)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

我收到以下异常:

Autofac.Core.Registration.ComponentNotRegisteredException:请求的服务'log4net.ILog'尚未注册.要避免此异常,请注册组件以提供服务,使用IsRegistered()检查服务注册,或使用ResolveOptional()方法解析可选依赖项.

nem*_*esv 9

您LogInjectionModule 从不ILog 在容器中注册任何内容只为准备面上的已解析实例提供参数,并且它仅适用于由Autofac创建的实例.

因此,当您编写时,builder.Register(x => new ClassThatNeedsILog(x.Resolve<ILog>()))您正在ClassThatNeedsILog手动创建.同new ClassThatNeedsILog(...)

因此,Autofac不知道你的实例创建(所以你OnComponentPreparing不会运行),因为你没有真正注册任何ILog实现,你得到了ComponentNotRegisteredException.

您有两种选择:

  • ILog直接在容器中注册
  • 让Autofac创建您的ClassThatNeedsILog类型.

所以你可以ILog在容器中注册一个:

builder.RegisterInstance(LogManager.GetLogger("Logger")).As<ILog>();
Run Code Online (Sandbox Code Playgroud)

然后你的代码将正常工作.

或者,无论如何你ClassThatNeedsILog手动创建可以直接提供ILog那里:

 builder.Register(x => new 
     ClassThatNeedsILog(LogManager.GetLogger(typeof(ClassThatNeedsILog))))
     .AsImplemen??tedInterfaces();
Run Code Online (Sandbox Code Playgroud)

其他选项是让Autofac为您创建实例,因此请将注册更改为:

 builder.RegisterType<ClassThatNeedsILog>()
     .AsImplemen??tedInterfaces();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Autofac将为您处理实例创建,它将调用OnComponentPreparing模块的方法.

如果要提供其他构造函数参数,可以使用WithParameter和WithParameters方法:

 builder.RegisterType<ClassThatNeedsILog>()
     .AsImplemen??tedInterfaces()
     .WithParameters(new Parameter[] {
         ResolvedParameter.ForNamed<IAnotherInterface>("NAME"),
         ResolvedParameter.ForNamed<IYetAnotherInterface>("ANOTHERNAME")});
Run Code Online (Sandbox Code Playgroud)