【问题标题】:Dependency on Log4Net Logger and Retrieve Logger by Caller Type using Castle Windsor使用 Castle Windsor 按调用者类型对 Log4Net 记录器和检索记录器的依赖
【发布时间】:2012-03-01 00:50:53
【问题描述】:

我在log4net 周围有一个薄包装器,我正在尝试使用调用类的类型通过使用Castle.Windsorlog4net.LogManager 获取记录器。

public class Foo: IFoo
{
    private readonly ICommonLog _logger;

    public Foo(ICommonLog logger)
    {
        _logger = logger;
    }

    public void FooBar()
    {
        _logger.Info("Enter FooBar Method");
    }
}

public class CommonLog : ICommonLog
{
    private readonly log4net.ILog _logger;

    public CommonLog(Type loggerType)
    {
        _logger = log4net.LogManager.GetLogger(loggerType); 
    }

    public void Info(string message)
    {         
        _logger.Info(message.Cleanse());
    }

    // ...
}

我已在Castle.Windsor (2.5.1) 中尝试过此注册,并且我能够为Foo 获取正确的记录器。我是否在这种情况下误用了动态参数?有没有更优雅的解决方案?

container.Register(Component.For<ICommonLog>().ImplementedBy(typeof(CommonLog)).
   LifeStyle.Transient);
container.Register(Component.For<IFoo>().ImplementedBy(typeof(Foo)).
   LifeStyle.Transient.DynamicParameters(
       (k, d) =>
       {
          var component = k.Resolve<ICommonLog>(new {loggerType = typeof (Foo)});
          d["logger"] = component;
          return r =>
          {
              if (component != null)
              {
                  r.ReleaseComponent(component);
              }
          };
       })
  );

编辑:我已经使用ISubDependencyResolver更新了解决方案:

public class LoggerResolver : ISubDependencyResolver
{
    private readonly IKernel kernel;

    public LoggerResolver(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public bool CanResolve(CreationContext context,
                           ISubDependencyResolver contextHandlerResolver,
                           ComponentModel model,
                           DependencyModel dependency)
    {
        return dependency.TargetType == typeof (ICommonLog);
    }

    public object Resolve(CreationContext context,
                          ISubDependencyResolver contextHandlerResolver,
                          ComponentModel model,
                          DependencyModel dependency)
    {
        if (CanResolve(context, contextHandlerResolver, model, dependency))
        {
            return kernel.Resolve<ICommonLog>(new {loggerType = model.Implementation});
        }
        return null;
    }
}

注册:

container.Register(Component.For<ICommonLog>().ImplementedBy(typeof(CommonLog))
    .LifeStyle.Transient);
container.Register(Component.For<IFoo().ImplementedBy(typeof(Foo))
    .LifeStyle.Transient);
container.Kernel.Resolver.AddSubResolver(new LoggerResolver(container.Kernel));

【问题讨论】:

  • 为什么不直接使用日志工具?
  • 您可以使用基于约定的方法。这是一个类似的问题(和答案):stackoverflow.com/questions/9339840/…
  • @MauricioScheffer 谢谢,我以前看过,可能会采用它而无需在这里重新发明轮子......
  • @MarkSeemann 感谢您的链接。我在这里看不到约定,但将您的示例用于ISubDependencyResolver 方法。

标签: c# .net inversion-of-control castle-windsor log4net


【解决方案1】:

您不需要注册 CommonLog。您的子依赖解析器可以为您新建一个。

container.Register(Component.For<IFoo>().ImplementedBy<Foo>().LifeStyle.Transient);
container.Kernel.Resolver.AddSubResolver(new LoggerResolver(container.Kernel));

public class LoggerResolver : ISubDependencyResolver
{
    ...

    public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
    {
        //No need to can resolve, Windsor will do this for you

        return new CommonLog(model.Implementation);
    }
}

记录器提供程序的编辑示例

container.Register(Component.For<ILoggerProvider>().ImplementedBy<Log4NetLoggerProvider >().LifeStyle.Transient);

public interface ICommonLoggerProvider
{
    ICommonLog GetLogger( Type type );
}

public class Log4NetLoggerProvider : ICommonLoggerProvider
{
    public ICommonLog GetLogger(Type type)
    {
        return new Log4NetLogger(type);
    }
}

public class LoggerResolver : ISubDependencyResolver
{
    ...
    public object Resolve( CreationContext context, ISubDependencyResolver contextHandlerResolver, Castle.Core.ComponentModel model, DependencyModel dependency )
    {
        return kernel.Resolve<ICommonLoggerProvider>().GetLogger( model.Implementation );
    }
}

【讨论】:

  • 好的,谢谢,但如果我想换出ICommonLog 的实现怎么办?最后,ComponentModel 不会公开 TargetType 属性。
  • @Luke Hutton - 我的错,只是看看我的实现,你使用了正确的属性,我已经更新了代码。如果您希望能够更换记录器,您可以引入您在 Windsor 中注册的提供者/工厂的概念。我已经更新了代码以显示我所做的但使用了您的类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-07
  • 1970-01-01
相关资源
最近更新 更多