关于《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);
}
}
}

浙公网安备 33010602011771号