Решение состоит в том, чтобы создать простой фасад регистратора, чтобы полностью отделить Ninject от остальной части приложения. Шаги:
1) Скопируйте / вставьте интерфейс Ninject ILogger в пространство имен приложения (не просто наследуйте, или вы в конечном итоге зависите от сборки Ninject из-за типов, предоставляемых через ILogger Ninject).
2) Создание пользовательских классов Logger, LoggerFactory и LoggerModule.
3) Передайте LoggerModule в StandardKernel Ninject
Для полноты код:
Ninject's 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);
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);
}
}
}
Уберите весь этот беспорядок в отдельную библиотеку классов, сделав ее единственной частью, зависящей от расширения ведения журнала 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. Вот и все.