解决方案是创建一个简单的记录器外观,以将 Ninject 与应用程序的其余部分完全分离。步骤是:
1) 将 Ninject 的 ILogger 接口复制/粘贴到应用程序的命名空间中(不要仅仅继承或最终依赖于 Ninject 的程序集,因为通过 Ninject 的 ILogger 公开的类型)。
2) 创建自定义Logger、LoggerFactory 和LoggerModule 类。
3) 将 LoggerModule 传递给 Ninject 的 StandardKernel
为了完整起见,代码是:
Ninject 的ILogger - 复制/粘贴 ILogger 接口,将其命名空间更改为 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);
}
}
}
记录器工厂.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;
}
}
}
}
记录器模块.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。就是这样。