c# - 洋葱架构日志记录 NHibernate

标签 c# nhibernate ninject nlog onion-architecture

我正在使用基于 this 的架构洋葱架构的实现。我决定挑战自己,用 NLog 更改 NHibernates 默认记录器 (log4net)。我了解如何配置 NLog,但我无法解决我对 LogerFactory 类中的记录器的依赖性。目前,我的 NHibernate 项目只知道我的日志接口(interface)。我怎样才能让我的 NHibernate 项目解决依赖关系?

这是我现在的程序结构: 控制台应用程序初始化 ninject 并设置我的模块,包括我的 LoggingModule 和我的 RepositoryModule。第一次我需要我的存储库中的东西时,我的 SessionHelper 类会构建我的 session 并配置 NHibernate。这是 NHibernate 调用我的 LoggerFactory 的地方(LoggerFactory 实现了 NHibernates ILoggerFactory)。 NHibernate 调用 LoggerFor(Type type);类型作为 NHibernate.Cfg.Configuration 传入。从这里开始,我需要通过我的 ILoggingService 获取 NLog 的实例,这是我感到困惑的地方。我如何解决这里的这种依赖?我的控制台应用程序知道分辨率,因为那是我构建内核和加载模块的地方。我只是在这里设置另一个内核吗?解决这个问题的最佳方法是什么?

编辑:这是我当前的代码:

程序.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 session 并进行配置。请注意,正在注入(inject) connectionString。我可以轻松地在此处注入(inject)日志记录服务。

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();
        }
    }
}

记录器工厂.cs 通过 app.config 为 NHibernate 配置以用于其日志记录。这是我遇到依赖性问题的地方。这与 NHibernate 一起存在。我可以在此处轻松引用 NLog 并将其与 NHibernate 连接起来,但我不希望 NHibernate 关心我使用的是什么日志记录框架。这就是为什么我只想处理我的接口(interface),让 Ninject 注入(inject)我的具体实现。

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;
        }

        //....
    }
}

最佳答案

为什么不能将静态内核属性添加到 LoggerFactory 类,并在初始化内核后立即在 Program.Main 中设置它?

然后在您的 LoggerFor 实现中,您只需引用静态内核属性即可获得正确绑定(bind)的实现。

关于c# - 洋葱架构日志记录 NHibernate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11090857/

相关文章:

c# - 使用 HttpWebRequest POST 到外部服务器上的表单

nhibernate - 仅使用 NHibernate 保留基类

nhibernate - 每个子类继承策略使用 NHibernate 表时的 Casting 代理问题

c# - Ninject 中的 transient 范围对象何时停用?

c# - 使用 ninject.extensions.factory - 根类中会发生什么?

c# - Ninject、Parallel.ForEach 和 InThreadScope()

c# - 如果不使用 lambda 表达式,这个 Parallel.ForEach 循环将如何完成?

c# - 为什么不 obj ? null 导致编译器警告

c# - 使用 defaultValue 时,如何在 Entity 框架中获取插入实体的 Id?

c# - 使用 NHibernate 截断或删除表中的所有数据