Ninject.Extensions.Logging.Log4net意外行为 [英] Ninject.Extensions.Logging.Log4net unexpected behavior

查看:395
本文介绍了Ninject.Extensions.Logging.Log4net意外行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过Ninject的(2.2.1.4)Extensions.Logging.Log4net(2.2.0.4)通过NuGet安装时使用Log4Net(1.2.10)有问题。



当我直接访问Log4Net时:

  var logger = log4net.LogManager.GetLogger(Log4NetLoggerTest); 
logger.Debug(foo {bar);

结果是:

  2011-08-29 10:02:02,071 [9] DEBUG Log4NetLoggerTest foo {bar 


$ b b

但是,当通过Ninject访问日志记录时:

 使用(IKernel kernel = new StandardKernel $ b {
var ninjectLogger = kernel.Get< NinjectLoggerTest>();
ninjectLogger.Log.Debug(foo {bar);
}

其中NinjectLoggerTest只是这样:

 使用Ninject.Extensions.Logging; 
命名空间TestApp
{
public class NinjectLoggerTest
{
public NinjectLoggerTest(ILogger log)
{
Log = log;
}
public ILogger Log;
}
}

有一些意想不到的结果是:

  2011-08-29 10:29:27,114 [10] DEBUG TestApp.NinjectLoggerTest< log4net.Error> StringFormat中的异常:输入字符串不是以正确的格式。 < format> foo {bar< / format>< args> {}< / args>< /log4net.Error>更糟糕的是,当使用ILogger的Trace方法时,类型'System.FormatException'有第一次机会异常。 'in mscorlib.dll 



我做错了什么?我可以如何解决这个问题?



TIA

解决方案

创建一个简单的记录器外观,完全解耦Ninject的应用程序的其余部分。步骤是:



1)将Ninject的ILogger界面复制/粘贴到应用程序的命名空间中(不仅仅继承或者最终取决于Ninject的程序集, Ninject的ILogger)。



3)将LoggerModule传递给LoggerModule Ninject的标准内核



为了完整性,代码为:



Ninject的 ILogger - 复制/粘贴ILogger界面,将其命名空间更改为MyAppNamespace .Logger并添加以下方法:

  void Debug 
void Info(string message);
void Trace(string message);
void Warn(string message);
void错误(字符串消息);
void致命(字符串消息);

Logger.cs

  namespace MyAppNamespace.Logger 
{
using System;
class Logger:Ninject.Extensions.Logging.Log4net.Infrastructure.Log4NetLogger,ILogger
{
private const string DumpVerbatimFormat ={0};

public Logger(Type type)
:base(type)
{
}

public void调试$ b {
base.Debug(DumpVerbatimFormat,message);
}

public void Info(string message)
{
base.Info(DumpVerbatimFormat,message);
}

public void Trace(string message)
{
base.Trace(DumpVerbatimFormat,message);
}

public void Warn(string message)
{
base.Warn(DumpVerbatimFormat,message);
}

public void错误(字符串消息)
{
base.Error(DumpVerbatimFormat,message);
}

public void致命(字符串消息)
{
base.Fatal(DumpVerbatimFormat,message);
}
}
}

LoggerFactory.cs

 命名空间MyAppNamespace.Logger 
{
using System;
using System.Collections.Generic;

static class LoggerFactory
{
public static ILogger GetLogger(Ninject.Activation.IContext context)
{
return GetLogger(context.Request.Target = = null?typeof(ILogger):context.Request.Target.Member.DeclaringType);
}

私有静态readonly字典< Type,ILogger> TypeToLoggerMap = new Dictionary< Type,ILogger>();

private static ILogger GetLogger(Type type)
{
lock(TypeToLoggerMap)
{
if(TypeToLoggerMap.ContainsKey(type))
return TypeToLoggerMap [type];

ILogger logger = new Logger(type);
TypeToLoggerMap.Add(type,logger);

return logger;
}
}
}
}

LoggerModule .cs

 命名空间MyAppNamespace.Logger 
{
public class LoggerModule:Ninject.Modules.NinjectModule
{
public override void Load()
{
log4net.Config.XmlConfigurator.Configure();
Bind< ILogger>()。ToMethod(LoggerFactory.GetLogger);
}
}
}

一个单独的类库使它成为唯一的依赖于Ninject的日志扩展和具体的记录器。您现在可以在整个应用程式中使用MyAppNamespace.ILogger,例如:



LoggerTest.cs

  namespace MyAppNamespace.Whatever 
{
使用Logger;
public class LoggerTest
{
public LoggerTest(ILogger log)
{
Log.Info(Logger startup up);
}
}
}

/ p>

 使用(IKernel kernel = new StandardKernel(new Logger.LoggerModule()))
{
kernel。 Get< LoggerTest>();
}

主要取决于Ninject,而不是日志记录扩展名和使用的记录器(代码适用于Log4Net,您需要为NLog调整一点)。应用程序的其他部分依赖于MyAppNamespace.ILogger。就是这样。


I am having a problem using Log4Net (1.2.10) through Ninject's (2.2.1.4) Extensions.Logging.Log4net (2.2.0.4), as installed through NuGet.

When I access Log4Net directly:

var logger = log4net.LogManager.GetLogger("Log4NetLoggerTest");
logger.Debug("foo { bar");

The result is:

2011-08-29 10:02:02,071 [9] DEBUG Log4NetLoggerTest foo { bar

However, when the logger is accessed through Ninject:

using (IKernel kernel = new StandardKernel())
{
    var ninjectLogger = kernel.Get<NinjectLoggerTest>();
    ninjectLogger.Log.Debug("foo { bar");
}

Where NinjectLoggerTest is simply this:

using Ninject.Extensions.Logging;
namespace TestApp
{
    public class NinjectLoggerTest
    {
        public NinjectLoggerTest(ILogger log)
        {
            Log = log;
        }
        public ILogger Log;
    }
}

Somewhat unexpectedly, the result is:

2011-08-29 10:29:27,114 [10] DEBUG TestApp.NinjectLoggerTest <log4net.Error>Exception during StringFormat: Input string was not in a correct format. <format>foo { bar</format><args>{}</args></log4net.Error>

Even worse, when using the ILogger's Trace method there is a first chance exception of type 'System.FormatException' in mscorlib.dll

Am I doing something wrong? How may I fix this?

TIA

解决方案

The solution is to create a simple logger façade to completely decouple Ninject from the rest of the app. The steps are:

1) Copy/paste Ninject's ILogger interface into the app's namespace (do not just inherit or you end up depending on Ninject's assembly because of the types exposed through Ninject's ILogger).

2) Create custom Logger, LoggerFactory and LoggerModule classes.

3) Pass LoggerModule to Ninject's StandardKernel

For completeness the code is:

Ninject's ILogger - copy/paste the ILogger interface, change it's namespace to MyAppNamespace.Logger and add the following methods:

void Debug(string message);
void Info(string message);
void Trace(string message);
void Warn(string message);
void Error(string message);
void Fatal(string message);

Logger.cs

namespace MyAppNamespace.Logger
{
    using System;
    class Logger : Ninject.Extensions.Logging.Log4net.Infrastructure.Log4NetLogger, ILogger
    {
        private const string DumpVerbatimFormat = "{0}";

        public Logger(Type type)
            : base(type)
        {
        }

        public void Debug(string message)
        {
            base.Debug(DumpVerbatimFormat, message);
        }

        public void Info(string message)
        {
            base.Info(DumpVerbatimFormat, message);
        }

        public void Trace(string message)
        {
            base.Trace(DumpVerbatimFormat, message);
        }

        public void Warn(string message)
        {
            base.Warn(DumpVerbatimFormat, message);
        }

        public void Error(string message)
        {
            base.Error(DumpVerbatimFormat, message);
        }

        public void Fatal(string message)
        {
            base.Fatal(DumpVerbatimFormat, message);
        }
    }
}

LoggerFactory.cs

namespace MyAppNamespace.Logger
{
    using System;
    using System.Collections.Generic;

    static class LoggerFactory
    {
        public static ILogger GetLogger(Ninject.Activation.IContext context)
        {
            return GetLogger(context.Request.Target == null ? typeof(ILogger) : context.Request.Target.Member.DeclaringType);
        }

        private static readonly Dictionary<Type, ILogger> TypeToLoggerMap = new Dictionary<Type, ILogger>();

        private static ILogger GetLogger(Type type)
        {
            lock (TypeToLoggerMap)
            {
                if (TypeToLoggerMap.ContainsKey(type))
                    return TypeToLoggerMap[type];

                ILogger logger = new Logger(type);
                TypeToLoggerMap.Add(type, logger);

                return logger;
            }
        }
    }
}

LoggerModule.cs

namespace MyAppNamespace.Logger
{
    public class LoggerModule : Ninject.Modules.NinjectModule
    {
        public override void Load()
        {
            log4net.Config.XmlConfigurator.Configure();
            Bind<ILogger>().ToMethod(LoggerFactory.GetLogger);
        }
    }
}

Tuck this whole mess away into a separate class library making it the only piece dependent on Ninject's logging extension and the concrete logger. You can now use MyAppNamespace.ILogger throughout your app, like this:

LoggerTest.cs

namespace MyAppNamespace.Whatever
{
    using Logger;
    public class LoggerTest
    {
        public LoggerTest(ILogger log)
        {
            Log.Info("Logger starting up");
        }
    }
}

somewhere in Main.cs

using (IKernel kernel = new StandardKernel(new Logger.LoggerModule()))
{
    kernel.Get<LoggerTest>();
}

Main ends up depending on Ninject but not the logging extension and whatever logger you use (the code works with Log4Net, you will need to tweak a bit for NLog). Other parts of the app depend on MyAppNamespace.ILogger. That's about it.

这篇关于Ninject.Extensions.Logging.Log4net意外行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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