Лук Архитектура Ведение журнала NHibernate
Я использую архитектуру, основанную на этой реализации луковой архитектуры. Я решил бросить вызов самому себе, чтобы поменять регистратор по умолчанию NHibernates (log4net) с NLog. Я понимаю, как настроить NLog, но у меня возникают проблемы с разрешением зависимости для моего регистратора в моем классе LogerFactory. В настоящее время мой проект NHibernate знает только мой интерфейс регистрации. Как я могу заставить свой проект NHibernate разрешить зависимость?
Это моя структура программы прямо сейчас: Консольное приложение инициализирует ninject и настраивает мои модули, включая мой LoggingModule и мой RepositoryModule. В самый первый раз, когда мне нужно что-то из моего репозитория, мой класс SessionHelper создает мой сеанс и настраивает NHibernate. Именно здесь NHibernate вызывает мой LoggerFactory (LoggerFactory реализует NHibernates ILoggerFactory). NHibernate вызывает LoggerFor(тип); тип передается как NHibernate.Cfg.Configuration. Отсюда мне нужно получить экземпляр NLog через мой ILoggingService, вот где я запутался. Как мне разрешить эту зависимость здесь? Мое консольное приложение знает о разрешении, потому что именно там я собрал ядро и загрузил модули. Я просто установил другое ядро здесь? Каков наилучший способ решить эту проблему?
Изменить: вот мой текущий код:
Program.cs
namespace ZeroBase.ManualConsole
{
class Program
{
static void Main(string[] args)
{
IKernel kernel = CreateKernel();
CoreService service = new CoreService(
kernel.Get<ZeroBase.Domain.Interfaces.IUserRepository>(),
kernel.Get<ZeroBase.Domain.Interfaces.ICommentRepository>());
//.........
}
static IKernel CreateKernel()
{
IKernel kernel = new StandardKernel();
RegisterServices(kernel);
return kernel;
}
static void RegisterServices(IKernel kernel)
{
// Bind Core Service
kernel.Bind<ICoreService>().To<CoreService>();
// Add data and infrastructure modules
var modules = new List<INinjectModule>
{
new ConfigModule(),
new LoggingModule(),
new RepositoryModule()
};
kernel.Load(modules);
}
}
}
LoggingModule.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject.Modules;
using ZeroBase.Infrastructure.Interfaces;
using NLog.Config;
using NLog;
using ZeroBase.Infrastructure.Logging;
namespace ZeroBase.Infrastructure.DependencyResolution
{
public class LoggingModule : NinjectModule
{
public override void Load()
{
ILoggingService logger = GetLoggingService();
Bind<ILoggingService>().ToConstant(logger);
}
private ILoggingService GetLoggingService()
{
ConfigurationItemFactory.Default.LayoutRenderers
.RegisterDefinition("utc_date", typeof(UtcDateRenderer));
ConfigurationItemFactory.Default.LayoutRenderers
.RegisterDefinition("web_variables", typeof(WebVariablesRenderer));
ILoggingService logger = (ILoggingService)LogManager.GetLogger("NLogLogger", typeof(LoggingService));
return logger;
}
}
}
RepositoryModule.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject;
using Ninject.Modules;
using ZeroBase.Infrastructure.Interfaces;
using ZeroBase.Domain.Interfaces;
using ZeroBase.Infrastructure.Data;
namespace ZeroBase.Infrastructure.DependencyResolution
{
public class RepositoryModule : NinjectModule
{
public override void Load()
{
SetupLogging();
BindRepositories();
}
private void SetupLogging()
{
// Get logging service
var loggingService = Kernel.Get<ILoggingService>();
}
private void BindRepositories()
{
// Get config service
var configService = Kernel.Get<IConfigService>();
// Bind repositories
Bind<IUserRepository>().To<UserRepository>()
.WithConstructorArgument("connectionString", configService.ZeroBaseConnection);
Bind<ICommentRepository>().To<CommentRepository>()
.WithConstructorArgument("connectionString", configService.ZeroBaseConnection);
}
}
}
RepositoryBase.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZeroBase.Domain.Interfaces;
namespace ZeroBase.Infrastructure.Data
{
public class RepositoryBase<T> : IRepositoryBase<T>
{
protected SessionHelper _nhibernate;
protected string _connectionString;
public RepositoryBase(string connectionString)
{
_connectionString = connectionString;
_nhibernate = new SessionHelper(_connectionString);
}
//....
}
}
SessionHelper.cs Создает сеанс NHibernate и настраивает его. Обратите внимание, что connectionString внедряется. Я мог бы легко внедрить службу регистрации здесь.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using ZeroBase.Infrastructure.Data;
using FluentNHibernate.Automapping;
using ZeroBase.Domain.Entities;
using ZeroBase.Infrastructure.Interfaces;
namespace ZeroBase.Infrastructure.Data
{
public class SessionHelper
{
private ISessionFactory _sessionFactory;
private string _connectionString;
public SessionHelper(string connectionString)
{
_connectionString = connectionString;
}
private ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
InitializeSessionFactory();
return _sessionFactory;
}
}
private void InitializeSessionFactory()
{
_sessionFactory = Fluently.Configure()
// Set up database connection
.Database(MsSqlConfiguration.MsSql2005
.ConnectionString(x => x.Is(_connectionString))
//.ShowSql()
)
// Use class mappings
.Mappings(m => m.FluentMappings
.AddFromAssemblyOf<UserMap>()
.AddFromAssemblyOf<ZeroBase.Infrastructure.Data.RACS3.UserMap>())
.ExposeConfiguration(c => {
c.SetInterceptor(new AuditInterceptor());
}
)
.BuildSessionFactory();
}
public ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
}
LoggerFactory.cs Настраивается с помощью app.config для NHibernate для использования в качестве журнала. Вот где у меня проблема с зависимостью. Это живет рядом с NHibernate. Я мог бы легко сослаться на NLog здесь и связать его с NHibernate, но я не хочу, чтобы NHibernate заботился о том, какую среду ведения журналов я использую. Вот почему я хотел бы иметь дело только с моим интерфейсом и позволить Ninject внедрить мою конкретную реализацию.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using ZeroBase.Infrastructure.Interfaces;
namespace ZeroBase.Infrastructure.Data
{
public class LoggerFactory : ILoggerFactory
{
public IInternalLogger LoggerFor(Type type)
{
//ILoggingService logService;
// Get resolved LoggingService
//return new NLogLogger(LogManager.GetLogger(type.FullName));
//return new Logger(logService.GetLogger(type.FullName));
return null;
}
public IInternalLogger LoggerFor(string keyName)
{
//ILoggingService logService;
// Get resolved LoggingService
//return new NLogLogger(LogManager.GetLogger(keyName));
//return new Logger(logService.GetLogger(keyName));
return null;
}
}
public class Logger : IInternalLogger
{
private readonly ILoggingService logger;
public Logger(ILoggingService _logger)
{
logger = _logger;
}
//....
}
}
2 ответа
Почему вы не можете добавить статическое свойство Kernal в свой класс LoggerFactory и установить его в свой Program.Main сразу после инициализации Kernal?
Затем в ваших реализациях LoggerFor вам просто нужно обратиться к вашему статическому свойству kernal, чтобы получить правильно связанную реализацию.
Использование NLog через Common.Logging с NHibernate:
http://nhibernate.info/doc/howto/various/using-nlog-via-common-logging-with-nhibernate.html