与登录模块注射时使用的ILog在Autofac明确的解决 [英] Explicit resolving of ILog in Autofac when using with Log Injection Module

查看:2815
本文介绍了与登录模块注射时使用的ILog在Autofac明确的解决的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用下面的代码,以便为需要它的所有类注册的log4net

 公共类LogInjectionModule:模块
{
私人只读字符串_configPath;

公共LogInjectionModule(串用configPath)
{
_configPath =用configPath;
}

保护覆盖无效AttachToComponentRegistration(IComponentRegistry注册表,
IComponentRegistration注册)
{
XmlConfigurator.Configure(新的FileInfo(_configPath));

registration.Preparing + = OnComponentPreparing;
}

私有静态无效OnComponentPreparing(对象发件人,PreparingEventArgs E)
{
变种T = e.Component.Activator.LimitType;
e.Parameters = e.Parameters.Union(新[]
{
新ResolvedParameter((P,I)=> p.ParameterType == typeof运算(ILog的),
(p,I)=> LogManager.GetLogger(t))的
});
}
}



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

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



,它工作正常!



一类需要显式注册尝试解决ILog的和失败

  builder.Register(X =>新建ClassThatNeedsILog(x.Resolve<&ILog的GT;()))AsImplementedInterfaces()。 

下面是类

 公共类ClassThatNeedsILog 
{
公共ClassThatNeedsILog(ILog的日志)
{

}
}

我收到以下异常:



<块引用>

Autofac.Core.Registration.ComponentNotRegisteredException:本
请求的服务'log4net.ILog'尚未注册。为了避免
这个例外,无论是注册一个组件提供服务,
进行服务注册使用IsRegistered()检查,或使用
ResolveOptional()方法来解决一个可选的依赖。



解决方案

LogInjectionModule 从不注册任何的ILog 倒入容器仅供paramters有关准备面对解决的情况下,它的仅适用于由Autofac创建的实例。



所以,当你写 builder.Register(X =>新建ClassThatNeedsILog(x.Resolve< ILog的>()))您正在创建的 ClassThatNeedsILog manully。与新ClassThatNeedsILog(...)



因此Autofac不知道你的实例创建(所以你的 OnComponentPreparing 将无法运行),因为你还没有真正注册你得到任何的ILog 实施 。ComponentNotRegisteredException



您有两种选择:




  • 注册一个的ILog 在容器中直接

  • 让Autofac创建 ClassThatNeedsILog 键入



所以,你可以与容器注册一个的ILog

  builder.RegisterInstance(LogManager.GetLogger(记录仪))为<&ILog的GT;(); 



那么你的代码将正常工作。



或者,如果你啦创建 ClassThatNeedsILog 用手可以只直接提供的ILog 有:

  builder.Register(X =>新建
ClassThatNeedsILog(LogManager.GetLogger (typeof运算(ClassThatNeedsILog))))
.AsImplemen tedInterfaces();



其他选项是让Autofac为您创建实例,所以更改登记:

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

在这种情况下,Autofac将处理实例创建适合你,它会调用 OnComponentPreparing 方法。



如果您要提供的额外的构造函数的参数你可以使用 WithParameter WithParameters 方法

  builder.RegisterType< ClassThatNeedsILog>()
.AsImplemen tedInterfaces()
.WithParameters(新的参数[] {
ResolvedParameter.ForNamed< IAnotherInterface>(NAME),
ResolvedParameter.ForNamed< IYetAnotherInterface>(ANOTHERNAME)});


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

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

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

And it works fine!

One class needs to be registered explicitly tries to resolve ILog and fails

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

Here is that class

public class ClassThatNeedsILog
{
    public ClassThatNeedsILog(ILog log)
    {

    }
}

I am getting the following exception:

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.

解决方案

Your LogInjectionModule never registers any ILog into the container only supplies paramters for the resolved instances on the preparing face, and it only works for instances created by Autofac.

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

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.

You have two options:

  • register an ILog in the container directly
  • let Autofac create your ClassThatNeedsILog type.

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

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

Then your code will work fine.

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

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

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

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

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

这篇关于与登录模块注射时使用的ILog在Autofac明确的解决的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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