gpt4 book ai didi

c#-4.0 - Ninject.Extensions.Logging.Log4net 意外行为

转载 作者:行者123 更新时间:2023-12-02 08:00:07 26 4
gpt4 key购买 nike

我通过 NuGet 安装的 Ninject (2.2.1.4) Extensions.Logging.Log4net (2.2.0.4) 使用 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

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

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

NinjectLoggerTest 就是这样:

using Ninject.Extensions.Logging;
namespace 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>Exception during StringFormat: Input string was not in a correct format. <format>foo { bar</format><args>{}</args></log4net.Error>

更糟糕的是,当使用 ILogger 的 Trace 方法时,mscorlib.dll 中首次出现“System.FormatException”类型的异常

我做错了什么吗?我该如何解决这个问题?

TIA

最佳答案

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

1) 将 Ninject 的 ILogger 接口(interface)复制/粘贴到应用程序的命名空间中(不要只是继承,否则您最终会依赖 Ninject 的程序集,因为通过 Ninject 的 ILogger 公开的类型)。

2) 创建自定义 Logger、LoggerFactory 和 LoggerModule 类。

3) 将 LoggerModule 传递给 Ninject 的 StandardKernel

为了完整起见,代码是:

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

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

记录器.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);
}
}
}

将这整个乱七八糟的东西塞进一个单独的类库中,使其成为唯一依赖于 Ninject 日志扩展和具体记录器的部分。您现在可以在整个应用程序中使用 MyAppNamespace.ILogger,如下所示:

LoggerTest.cs

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

Main.cs 中的某处

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

Main 最终取决于 Ninject,但不依赖于日志扩展以及您使用的任何记录器(代码适用于 Log4Net,您需要针对 NLog 进行一些调整)。应用程序的其他部分依赖于 MyAppNamespace.ILogger。就是这样。

关于c#-4.0 - Ninject.Extensions.Logging.Log4net 意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7227628/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com