与日志注入模块一起使用时,Autofac 中 ILog 的显式解析 [英] Explicit resolving of ILog in Autofac when using with Log Injection Module

查看:31
本文介绍了与日志注入模块一起使用时,Autofac 中 ILog 的显式解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I use the following code in order to register log4net for all the classes that need it.

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

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

All the classes are registered using autofac's types scanning:

builder.RegisterAssemblyTypes(typeof (IResourceFinder).Assembly)
 .AsImplementedInterfaces();

而且效果很好!

需要显式注册的一个类尝试解析 ILog 并失败

builder.Register(x => new ClassThatNeedsILog(x.Resolve<ILog>())).AsImplementedInterfaces();

这是那个班

public class ClassThatNeedsILog
{
    public ClassThatNeedsILog(ILog log)
    {

    }
}

我收到以下异常:

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

Autofac.Core.Registration.ComponentNotRegisteredException : 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.

推荐答案

你的 LogInjectionModule 从不注册任何 ILog 到容器只提供参数对于准备面上的已解析实例,它仅适用于 Autofac 创建的实例.

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

So when you write builder.Register(x => new ClassThatNeedsILog(x.Resolve<ILog>())) you are creating the ClassThatNeedsILog manually. with new ClassThatNeedsILog(...)

因此 Autofac 不知道您的实例创建(因此您的 OnComponentPreparing 不会运行)并且因为您还没有真正注册任何 ILog 实现,您将获得 <代码>ComponentNotRegisteredException.

Hence Autofac does not know about your instance creation (so your OnComponentPreparing won't run) and because you haven't really registered any ILog implementation you get the ComponentNotRegisteredException.

您有两个选择:

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

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

So you can just register an ILog in the container with:

builder.RegisterInstance(LogManager.GetLogger("Logger")).As<ILog>();

那么你的代码就可以正常工作了.

Then your code will work fine.

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

Or if you anyway creating the ClassThatNeedsILog by hand can just supply directly the ILog there:

 builder.Register(x => new 
     ClassThatNeedsILog(LogManager.GetLogger(typeof(ClassThatNeedsILog))))
     .AsImplemen‌​tedInterfaces();

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

The other options is to let Autofac create the instances for you, so change your registration to:

 builder.RegisterType<ClassThatNeedsILog>()
     .AsImplemen‌​tedInterfaces();

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

In this case Autofac will handle the instance creation for you and it will call the OnComponentPreparing method of your module.

如果您想提供其他构造函数参数,您可以使用WithParameterWithParameters 方法:

If you want to supply additional constructor parameters you can use WithParameter and WithParameters methods:

 builder.RegisterType<ClassThatNeedsILog>()
     .AsImplemen‌​tedInterfaces()
     .WithParameters(new Parameter[] {
         ResolvedParameter.ForNamed<IAnotherInterface>("NAME"),
         ResolvedParameter.ForNamed<IYetAnotherInterface>("ANOTHERNAME")});

这篇关于与日志注入模块一起使用时,Autofac 中 ILog 的显式解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆