Skip to content

Commit 94bcb21

Browse files
Have more robust log4net loading (#1837)
Co-Authored-By: Alexander Zaytsev <hazzik@gmail.com>
1 parent 051cc87 commit 94bcb21

File tree

2 files changed

+69
-33
lines changed

2 files changed

+69
-33
lines changed

src/NHibernate/Logging.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22
using System.Configuration;
3-
using System.IO;
43
using System.Linq;
54

65
namespace NHibernate
@@ -117,13 +116,8 @@ private static string GetNhibernateLoggerClass()
117116
string nhibernateLoggerClass = null;
118117
if (string.IsNullOrEmpty(nhibernateLogger))
119118
{
120-
// look for log4net.dll
121-
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
122-
string relativeSearchPath = AppDomain.CurrentDomain.RelativeSearchPath;
123-
string binPath = relativeSearchPath == null ? baseDir : Path.Combine(baseDir, relativeSearchPath);
124-
string log4NetDllPath = binPath == null ? "log4net.dll" : Path.Combine(binPath, "log4net.dll");
125-
126-
if (File.Exists(log4NetDllPath) || AppDomain.CurrentDomain.GetAssemblies().Any(a => a.GetName().Name == "log4net"))
119+
// look for log4net
120+
if (Log4NetLoggerFactory.Log4NetAssembly != null)
127121
{
128122
nhibernateLoggerClass = typeof(Log4NetLoggerFactory).AssemblyQualifiedName;
129123
}

src/NHibernate/Logging.log4net.cs

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Linq;
23
using System.Linq.Expressions;
34
using System.Reflection;
45
using NHibernate.Util;
@@ -12,16 +13,48 @@ namespace NHibernate
1213
public class Log4NetLoggerFactory: ILoggerFactory
1314
#pragma warning restore 618
1415
{
15-
private static readonly System.Type LogManagerType = System.Type.GetType("log4net.LogManager, log4net");
16+
internal static readonly Assembly Log4NetAssembly;
17+
private static readonly System.Type LogManagerType;
1618
private static readonly Func<Assembly, string, object> GetLoggerByNameDelegate;
1719
private static readonly Func<System.Type, object> GetLoggerByTypeDelegate;
1820

1921
static Log4NetLoggerFactory()
2022
{
23+
LogManagerType = GetLogManagerType();
24+
if (LogManagerType == null)
25+
return;
26+
27+
Log4NetAssembly = LogManagerType.Assembly;
2128
GetLoggerByNameDelegate = GetGetLoggerByNameMethodCall();
2229
GetLoggerByTypeDelegate = GetGetLoggerMethodCall<System.Type>();
2330
}
2431

32+
public Log4NetLoggerFactory()
33+
{
34+
if (LogManagerType == null)
35+
throw new TypeLoadException("Cannot find log4net.LogManager type");
36+
}
37+
38+
// Code adapted from ReflectHelper.TypeFromAssembly, which cannot be called directly due
39+
// to depending on the logger.
40+
private static System.Type GetLogManagerType()
41+
{
42+
var typeName = "log4net.LogManager, log4net";
43+
// Try to get the type from an already loaded assembly
44+
var type = System.Type.GetType(typeName);
45+
if (type != null)
46+
return type;
47+
48+
// Load type from an already loaded assembly, or yield null
49+
return System.Type.GetType(
50+
typeName,
51+
// An alternate could be "a.GetName().Name == an.Name", but GetName() is not lightweight.
52+
// "a.FullName == an.FullName" can never match because an.FullName will lack the version, culture
53+
// and public key token.
54+
an => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName.StartsWith("log4net,")),
55+
null);
56+
}
57+
2558
#pragma warning disable 618
2659
[Obsolete("Use this as an INHibernateLoggerFactory instead.")]
2760
public IInternalLogger LoggerFor(string keyName)
@@ -39,6 +72,8 @@ public IInternalLogger LoggerFor(System.Type type)
3972
private static Func<TParameter, object> GetGetLoggerMethodCall<TParameter>()
4073
{
4174
var method = LogManagerType.GetMethod("GetLogger", new[] { typeof(TParameter) });
75+
if (method == null)
76+
throw new InvalidOperationException($"Unable to find LogManager.GetLogger({typeof(TParameter)})");
4277
ParameterExpression resultValue;
4378
ParameterExpression keyParam = Expression.Parameter(typeof(TParameter), "key");
4479
MethodCallExpression methodCall = Expression.Call(null, method, resultValue = keyParam);
@@ -48,6 +83,8 @@ private static Func<TParameter, object> GetGetLoggerMethodCall<TParameter>()
4883
private static Func<Assembly, string, object> GetGetLoggerByNameMethodCall()
4984
{
5085
var method = LogManagerType.GetMethod("GetLogger", new[] {typeof(Assembly), typeof(string)});
86+
if (method == null)
87+
throw new InvalidOperationException("Unable to find LogManager.GetLogger(Assembly, string)");
5188
ParameterExpression nameParam = Expression.Parameter(typeof(string), "name");
5289
ParameterExpression repositoryAssemblyParam = Expression.Parameter(typeof(Assembly), "repositoryAssembly");
5390
MethodCallExpression methodCall = Expression.Call(null, method, repositoryAssemblyParam, nameParam);
@@ -62,7 +99,6 @@ private static Func<Assembly, string, object> GetGetLoggerByNameMethodCall()
6299
public class Log4NetLogger : IInternalLogger
63100
#pragma warning restore 618
64101
{
65-
private static readonly System.Type ILogType = System.Type.GetType("log4net.ILog, log4net");
66102
private static readonly Func<object, bool> IsErrorEnabledDelegate;
67103
private static readonly Func<object, bool> IsFatalEnabledDelegate;
68104
private static readonly Func<object, bool> IsDebugEnabledDelegate;
@@ -92,29 +128,35 @@ public class Log4NetLogger : IInternalLogger
92128

93129
static Log4NetLogger()
94130
{
95-
IsErrorEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(ILogType, "IsErrorEnabled");
96-
IsFatalEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(ILogType, "IsFatalEnabled");
97-
IsDebugEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(ILogType, "IsDebugEnabled");
98-
IsInfoEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(ILogType, "IsInfoEnabled");
99-
IsWarnEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(ILogType, "IsWarnEnabled");
100-
ErrorDelegate = DelegateHelper.BuildAction<object>(ILogType, "Error");
101-
ErrorExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(ILogType, "Error");
102-
ErrorFormatDelegate = DelegateHelper.BuildAction<string, object[]>(ILogType, "ErrorFormat");
103-
104-
FatalDelegate = DelegateHelper.BuildAction<object>(ILogType, "Fatal");
105-
FatalExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(ILogType, "Fatal");
106-
107-
DebugDelegate = DelegateHelper.BuildAction<object>(ILogType, "Debug");
108-
DebugExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(ILogType, "Debug");
109-
DebugFormatDelegate = DelegateHelper.BuildAction<string, object[]>(ILogType, "DebugFormat");
110-
111-
InfoDelegate = DelegateHelper.BuildAction<object>(ILogType, "Info");
112-
InfoExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(ILogType, "Info");
113-
InfoFormatDelegate = DelegateHelper.BuildAction<string, object[]>(ILogType, "InfoFormat");
114-
115-
WarnDelegate = DelegateHelper.BuildAction<object>(ILogType, "Warn");
116-
WarnExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(ILogType, "Warn");
117-
WarnFormatDelegate = DelegateHelper.BuildAction<string, object[]>(ILogType, "WarnFormat");
131+
if (Log4NetLoggerFactory.Log4NetAssembly == null)
132+
throw new TypeLoadException(
133+
"Cannot load ILog type, log4net is not found");
134+
135+
var iLogType = Log4NetLoggerFactory.Log4NetAssembly.GetType("log4net.ILog", true);
136+
137+
IsErrorEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(iLogType, "IsErrorEnabled");
138+
IsFatalEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(iLogType, "IsFatalEnabled");
139+
IsDebugEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(iLogType, "IsDebugEnabled");
140+
IsInfoEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(iLogType, "IsInfoEnabled");
141+
IsWarnEnabledDelegate = DelegateHelper.BuildPropertyGetter<bool>(iLogType, "IsWarnEnabled");
142+
ErrorDelegate = DelegateHelper.BuildAction<object>(iLogType, "Error");
143+
ErrorExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(iLogType, "Error");
144+
ErrorFormatDelegate = DelegateHelper.BuildAction<string, object[]>(iLogType, "ErrorFormat");
145+
146+
FatalDelegate = DelegateHelper.BuildAction<object>(iLogType, "Fatal");
147+
FatalExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(iLogType, "Fatal");
148+
149+
DebugDelegate = DelegateHelper.BuildAction<object>(iLogType, "Debug");
150+
DebugExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(iLogType, "Debug");
151+
DebugFormatDelegate = DelegateHelper.BuildAction<string, object[]>(iLogType, "DebugFormat");
152+
153+
InfoDelegate = DelegateHelper.BuildAction<object>(iLogType, "Info");
154+
InfoExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(iLogType, "Info");
155+
InfoFormatDelegate = DelegateHelper.BuildAction<string, object[]>(iLogType, "InfoFormat");
156+
157+
WarnDelegate = DelegateHelper.BuildAction<object>(iLogType, "Warn");
158+
WarnExceptionDelegate = DelegateHelper.BuildAction<object, Exception>(iLogType, "Warn");
159+
WarnFormatDelegate = DelegateHelper.BuildAction<string, object[]>(iLogType, "WarnFormat");
118160
}
119161

120162
/// <summary>

0 commit comments

Comments
 (0)