关于《NHibernate中使用NLog》中在App.config(web.config)中增加nhibernate-logger节点的疑惑

在上一篇《 NHibernate中使用NLog》中最后在App.config或web.config中AppSettings节中增加nhibernate-logger节点的介绍比较含糊,引起了朋友的疑问,现在在这里关于这个节点进行详细的讲解。
首先我们先看一下NH3的源码:NHibernate-3.1.0.GA/src/NHibernate/Logging.cs
在该代码中获取AppSetttings节的配置节点的部门,如果它没有检测到用户的程序中配置了自定义的Log框架情况时则检测LOG4NET是否存在,如果存在则使用LOG4NET来记录LOG。另外NH3中也提供了LOG4NET的实现,可以看出NH3中对于LOG4NET的实现非常的灵活,我准备在下一篇文章中根据NH3中对于LOG4NET的实现方式来实现NLOG框架而不是象 NHibernate中使用NLog中入门的方式来实现接口。
using System;

using System.Configuration;

using System.IO;

using System.Linq;

using System.Linq.Expressions;



namespace NHibernate

{

	public interface IInternalLogger

	{

		bool IsErrorEnabled { get; }

		bool IsFatalEnabled { get; }

		bool IsDebugEnabled { get; }

		bool IsInfoEnabled { get; }

		bool IsWarnEnabled { get; }

		void Error(object message);

		void Error(object message, Exception exception);

		void ErrorFormat(string format, params object[] args);



		void Fatal(object message);

		void Fatal(object message, Exception exception);



		void Debug(object message);

		void Debug(object message, Exception exception);

		void DebugFormat(string format, params object[] args);



		void Info(object message);

		void Info(object message, Exception exception);

		void InfoFormat(string format, params object[] args);



		void Warn(object message);

		void Warn(object message, Exception exception);

		void WarnFormat(string format, params object[] args);

	}



	public interface ILoggerFactory

	{

		IInternalLogger LoggerFor(string keyName);

		IInternalLogger LoggerFor(System.Type type);

	}



	public class LoggerProvider

	{

		private const string NhibernateLoggerConfKey = "nhibernate-logger";

		private readonly ILoggerFactory loggerFactory;

		private static LoggerProvider instance;



		static LoggerProvider()

		{

			string nhibernateLoggerClass = GetNhibernateLoggerClass();

			ILoggerFactory loggerFactory = string.IsNullOrEmpty(nhibernateLoggerClass) ? new NoLoggingLoggerFactory() : GetLoggerFactory(nhibernateLoggerClass);

			SetLoggersFactory(loggerFactory);

		}



		private static ILoggerFactory GetLoggerFactory(string nhibernateLoggerClass)

		{

			ILoggerFactory loggerFactory;

			var loggerFactoryType = System.Type.GetType(nhibernateLoggerClass);

			try

			{

				loggerFactory = (ILoggerFactory) Activator.CreateInstance(loggerFactoryType);

			}

			catch (MissingMethodException ex)

			{

				throw new ApplicationException("Public constructor was not found for " + loggerFactoryType, ex);

			}

			catch (InvalidCastException ex)

			{

				throw new ApplicationException(loggerFactoryType + "Type does not implement " + typeof (ILoggerFactory), ex);

			}

			catch (Exception ex)

			{

				throw new ApplicationException("Unable to instantiate: " + loggerFactoryType, ex);

			}

			return loggerFactory;

		}



		private static string GetNhibernateLoggerClass()

		{

			var nhibernateLogger = ConfigurationManager.AppSettings.Keys.Cast<string>().FirstOrDefault(k => NhibernateLoggerConfKey.Equals(k.ToLowerInvariant()));

			string nhibernateLoggerClass = null;

			if (string.IsNullOrEmpty(nhibernateLogger))

			{

				// look for log4net.dll

				string baseDir = AppDomain.CurrentDomain.BaseDirectory;

				string relativeSearchPath = AppDomain.CurrentDomain.RelativeSearchPath;

				string binPath = relativeSearchPath == null ? baseDir : Path.Combine(baseDir, relativeSearchPath);

				var log4NetDllPath = Path.Combine(binPath, "log4net.dll");



				if (File.Exists(log4NetDllPath))

				{

					nhibernateLoggerClass = typeof (Log4NetLoggerFactory).AssemblyQualifiedName;

				}

			}

			else

			{

				nhibernateLoggerClass = ConfigurationManager.AppSettings[nhibernateLogger];

			}

			return nhibernateLoggerClass;

		}



		public static void SetLoggersFactory(ILoggerFactory loggerFactory)

		{

			instance = new LoggerProvider(loggerFactory);

		}



		private LoggerProvider(ILoggerFactory loggerFactory)

		{

			this.loggerFactory = loggerFactory;

		}



		public static IInternalLogger LoggerFor(string keyName)

		{

			return instance.loggerFactory.LoggerFor(keyName);

		}



		public static IInternalLogger LoggerFor(System.Type type)

		{

			return instance.loggerFactory.LoggerFor(type);

		}

	}



	public class NoLoggingLoggerFactory: ILoggerFactory

	{

		private static readonly IInternalLogger Nologging = new NoLoggingInternalLogger();

		public IInternalLogger LoggerFor(string keyName)

		{

			return Nologging;

		}



		public IInternalLogger LoggerFor(System.Type type)

		{

			return Nologging;

		}

	}



	public class NoLoggingInternalLogger: IInternalLogger

	{

		public bool IsErrorEnabled

		{

			get { return false;}

		}



		public bool IsFatalEnabled

		{

			get { return false; }

		}



		public bool IsDebugEnabled

		{

			get { return false; }

		}



		public bool IsInfoEnabled

		{

			get { return false; }

		}



		public bool IsWarnEnabled

		{

			get { return false; }

		}



		public void Error(object message)

		{

		}



		public void Error(object message, Exception exception)

		{

		}



		public void ErrorFormat(string format, params object[] args)

		{

		}



		public void Fatal(object message)

		{

		}



		public void Fatal(object message, Exception exception)

		{

		}



		public void Debug(object message)

		{

		}



		public void Debug(object message, Exception exception)

		{

		}



		public void DebugFormat(string format, params object[] args)

		{

		}



		public void Info(object message)

		{

		}



		public void Info(object message, Exception exception)

		{

		}



		public void InfoFormat(string format, params object[] args)

		{

		}



		public void Warn(object message)

		{

		}



		public void Warn(object message, Exception exception)

		{

		}



		public void WarnFormat(string format, params object[] args)

		{

		}

	}



	public class Log4NetLoggerFactory: ILoggerFactory

	{

		private static readonly System.Type LogManagerType = System.Type.GetType("log4net.LogManager, log4net");

		private static readonly Func<string, object> GetLoggerByNameDelegate;

		private static readonly Func<System.Type, object> GetLoggerByTypeDelegate;

		static Log4NetLoggerFactory()

		{

			GetLoggerByNameDelegate = GetGetLoggerMethodCall<string>();

			GetLoggerByTypeDelegate = GetGetLoggerMethodCall<System.Type>();

		}

		public IInternalLogger LoggerFor(string keyName)

		{

			return new Log4NetLogger(GetLoggerByNameDelegate(keyName));

		}



		public IInternalLogger LoggerFor(System.Type type)

		{

			return new Log4NetLogger(GetLoggerByTypeDelegate(type));

		}



		private static Func<TParameter, object> GetGetLoggerMethodCall<TParameter>()

		{

			var method = LogManagerType.GetMethod("GetLogger", new[] { typeof(TParameter) });

			ParameterExpression resultValue;

			ParameterExpression keyParam = Expression.Parameter(typeof(TParameter), "key");

			MethodCallExpression methodCall = Expression.Call(null, method, new Expression[] { resultValue = keyParam });

			return Expression.Lambda<Func<TParameter, object>>(methodCall, new[] { resultValue }).Compile();

		}

	}



	public class Log4NetLogger: IInternalLogger

	{

		private static readonly System.Type ILogType = System.Type.GetType("log4net.ILog, log4net");

		private static readonly Func<object, bool> IsErrorEnabledDelegate;

		private static readonly Func<object, bool> IsFatalEnabledDelegate;

		private static readonly Func<object, bool> IsDebugEnabledDelegate;

		private static readonly Func<object, bool> IsInfoEnabledDelegate;

		private static readonly Func<object, bool> IsWarnEnabledDelegate;



		private static readonly Action<object, object> ErrorDelegate;

		private static readonly Action<object, object, Exception> ErrorExceptionDelegate;

		private static readonly Action<object, string, object[]> ErrorFormatDelegate;



		private static readonly Action<object, object> FatalDelegate;

		private static readonly Action<object, object, Exception> FatalExceptionDelegate;



		private static readonly Action<object, object> DebugDelegate;

		private static readonly Action<object, object, Exception> DebugExceptionDelegate;

		private static readonly Action<object, string, object[]> DebugFormatDelegate;



		private static readonly Action<object, object> InfoDelegate;

		private static readonly Action<object, object, Exception> InfoExceptionDelegate;

		private static readonly Action<object, string, object[]> InfoFormatDelegate;



		private static readonly Action<object, object> WarnDelegate;

		private static readonly Action<object, object, Exception> WarnExceptionDelegate;

		private static readonly Action<object, string, object[]> WarnFormatDelegate;



		private readonly object logger;



		static Log4NetLogger()

		{

			IsErrorEnabledDelegate = GetPropertyGetter("IsErrorEnabled");

			IsFatalEnabledDelegate = GetPropertyGetter("IsFatalEnabled");

			IsDebugEnabledDelegate = GetPropertyGetter("IsDebugEnabled");

			IsInfoEnabledDelegate = GetPropertyGetter("IsInfoEnabled");

			IsWarnEnabledDelegate = GetPropertyGetter("IsWarnEnabled");

			ErrorDelegate = GetMethodCallForMessage("Error");

			ErrorExceptionDelegate = GetMethodCallForMessageException("Error");

			ErrorFormatDelegate = GetMethodCallForMessageFormat("ErrorFormat");



			FatalDelegate = GetMethodCallForMessage("Fatal");

			FatalExceptionDelegate = GetMethodCallForMessageException("Fatal");



			DebugDelegate = GetMethodCallForMessage("Debug");

			DebugExceptionDelegate = GetMethodCallForMessageException("Debug");

			DebugFormatDelegate = GetMethodCallForMessageFormat("DebugFormat");



			InfoDelegate = GetMethodCallForMessage("Info");

			InfoExceptionDelegate = GetMethodCallForMessageException("Info");

			InfoFormatDelegate = GetMethodCallForMessageFormat("InfoFormat");



			WarnDelegate = GetMethodCallForMessage("Warn");

			WarnExceptionDelegate = GetMethodCallForMessageException("Warn");

			WarnFormatDelegate = GetMethodCallForMessageFormat("WarnFormat");

		}



		private static Func<object, bool> GetPropertyGetter(string propertyName)

		{

			ParameterExpression funcParam = Expression.Parameter(typeof(object), "l");

			Expression convertedParam = Expression.Convert(funcParam, ILogType);

			Expression property = Expression.Property(convertedParam, propertyName);

			return (Func<object, bool>)Expression.Lambda(property, funcParam).Compile();

		}



		private static Action<object, object> GetMethodCallForMessage(string methodName)

		{

			ParameterExpression loggerParam = Expression.Parameter(typeof(object), "l");

			ParameterExpression messageParam = Expression.Parameter(typeof(object), "o");

			Expression convertedParam = Expression.Convert(loggerParam, ILogType);

			MethodCallExpression methodCall = Expression.Call(convertedParam, ILogType.GetMethod(methodName, new[] { typeof(object) }), messageParam);

			return (Action<object, object>)Expression.Lambda(methodCall, new[] { loggerParam, messageParam }).Compile();

		}



		private static Action<object, object, Exception> GetMethodCallForMessageException(string methodName)

		{

			ParameterExpression loggerParam = Expression.Parameter(typeof(object), "l");

			ParameterExpression messageParam = Expression.Parameter(typeof(object), "o");

			ParameterExpression exceptionParam = Expression.Parameter(typeof(Exception), "e");

			Expression convertedParam = Expression.Convert(loggerParam, ILogType);

			MethodCallExpression methodCall = Expression.Call(convertedParam, ILogType.GetMethod(methodName, new[] { typeof(object), typeof(Exception) }), messageParam, exceptionParam);

			return (Action<object, object, Exception>)Expression.Lambda(methodCall, new[] { loggerParam, messageParam, exceptionParam }).Compile();

		}



		private static Action<object, string, object[]> GetMethodCallForMessageFormat(string methodName)

		{

			ParameterExpression loggerParam = Expression.Parameter(typeof(object), "l");

			ParameterExpression formatParam = Expression.Parameter(typeof(string), "f");

			ParameterExpression parametersParam = Expression.Parameter(typeof(object[]), "p");

			Expression convertedParam = Expression.Convert(loggerParam, ILogType);

			MethodCallExpression methodCall = Expression.Call(convertedParam, ILogType.GetMethod(methodName, new[] { typeof(string), typeof(object[]) }), formatParam, parametersParam);

			return (Action<object, string, object[]>)Expression.Lambda(methodCall, new[] { loggerParam, formatParam, parametersParam }).Compile();

		}



		public Log4NetLogger(object logger)

		{

			this.logger = logger;

		}



		public bool IsErrorEnabled

		{

			get { return IsErrorEnabledDelegate(logger); }

		}



		public bool IsFatalEnabled

		{

			get { return IsFatalEnabledDelegate(logger); }

		}



		public bool IsDebugEnabled

		{

			get { return IsDebugEnabledDelegate(logger); }

		}



		public bool IsInfoEnabled

		{

			get { return IsInfoEnabledDelegate(logger); }

		}



		public bool IsWarnEnabled

		{

			get { return IsWarnEnabledDelegate(logger); }

		}



		public void Error(object message)

		{

			ErrorDelegate(logger, message);

		}



		public void Error(object message, Exception exception)

		{

			ErrorExceptionDelegate(logger,message,exception);

		}



		public void ErrorFormat(string format, params object[] args)

		{

			ErrorFormatDelegate(logger, format, args);

		}



		public void Fatal(object message)

		{

			FatalDelegate(logger, message);

		}



		public void Fatal(object message, Exception exception)

		{

			FatalExceptionDelegate(logger,message,exception);

		}



		public void Debug(object message)

		{

			DebugDelegate(logger, message);

		}



		public void Debug(object message, Exception exception)

		{

			DebugExceptionDelegate(logger, message, exception);

		}



		public void DebugFormat(string format, params object[] args)

		{

			DebugFormatDelegate(logger, format, args);

		}



		public void Info(object message)

		{

			InfoDelegate(logger, message);

		}



		public void Info(object message, Exception exception)

		{

			InfoExceptionDelegate(logger, message, exception);

		}



		public void InfoFormat(string format, params object[] args)

		{

			InfoFormatDelegate(logger, format, args);

		}



		public void Warn(object message)

		{

			WarnDelegate(logger, message);

		}



		public void Warn(object message, Exception exception)

		{

			WarnExceptionDelegate(logger, message, exception);

		}



		public void WarnFormat(string format, params object[] args)

		{

			WarnFormatDelegate(logger, format, args);

		}

	}

}

你可能感兴趣的:(Hibernate)