Skip to content

Commit 3a439fe

Browse files
committed
Clearing pools via delegates
1 parent 3a307a0 commit 3a439fe

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

src/NHibernate/Driver/ReflectionBasedDriver.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Data.Common;
3+
using System.Linq.Expressions;
34
using System.Reflection;
45
using NHibernate.Util;
56

@@ -86,18 +87,18 @@ protected static class PoolHelper<T> where T : IDriver
8687
{
8788
// Static field in generic class => one field per concrete type used. This is exactly what
8889
// we need here, do not move the generic argument to the method. Otherwise it will cache the
89-
// method info of the first driver type used, and reuse it for other driver types, which
90+
// delegate of the first driver type used, and reuse it for other driver types, which
9091
// would fail.
91-
private static volatile MethodInfo _clearPool;
92-
private static volatile MethodInfo _clearAllPools;
92+
private static volatile System.Action<DbConnection> _clearPool;
93+
private static volatile System.Action _clearAllPools;
9394

9495
/// <summary>
9596
/// Clears the connection pool.
9697
/// </summary>
9798
/// <param name="driver">The driver for which the connection pool has to be cleared.</param>
9899
/// <param name="connectionString">The connection string of connections for which to clear the pool.
99100
/// <c>null</c> for clearing them all.</param>
100-
internal static void ClearPool(T driver, string connectionString)
101+
public static void ClearPool(T driver, string connectionString)
101102
{
102103
// In case of concurrent threads, may initialize many times. We do not care.
103104
// Members are volatile for avoiding they get used while their constructor is not yet ended.
@@ -106,8 +107,14 @@ internal static void ClearPool(T driver, string connectionString)
106107
using (var clearConnection = driver.CreateConnection())
107108
{
108109
var connectionType = clearConnection.GetType();
109-
_clearPool = connectionType.GetMethod("ClearPool") ?? throw new InvalidOperationException("Unable to resolve ClearPool method.");
110-
_clearAllPools = connectionType.GetMethod("ClearAllPools") ?? throw new InvalidOperationException("Unable to resolve ClearAllPools method.");
110+
111+
var clearPoolMethodInfo = GetMethod(connectionType, "ClearPool");
112+
var parameter = Expression.Parameter(typeof(DbConnection));
113+
var methodCall = Expression.Call(clearPoolMethodInfo, Expression.Convert(parameter, connectionType));
114+
_clearPool = Expression.Lambda<Action<DbConnection>>(methodCall, parameter).Compile();
115+
116+
var clearAllPoolsMethodInfo = GetMethod(connectionType, "ClearAllPools");
117+
_clearAllPools = (System.Action) Delegate.CreateDelegate(typeof(System.Action), clearAllPoolsMethodInfo);
111118
}
112119
}
113120

@@ -116,12 +123,17 @@ internal static void ClearPool(T driver, string connectionString)
116123
using (var clearConnection = driver.CreateConnection())
117124
{
118125
clearConnection.ConnectionString = connectionString;
119-
_clearPool.Invoke(null, new object[] {clearConnection});
126+
_clearPool(clearConnection);
120127
}
121128
return;
122129
}
123130

124-
_clearAllPools.Invoke(null, Array.Empty<object>());
131+
_clearAllPools();
132+
}
133+
134+
private static MethodInfo GetMethod(System.Type type, string methodName)
135+
{
136+
return type.GetMethod(methodName) ?? throw new InvalidOperationException($"Unable to resolve {type.Name}.{methodName} method.");
125137
}
126138
}
127139
}

0 commit comments

Comments
 (0)