Skip to content

Commit b256937

Browse files
committed
Added a fallback mechanism for internal types when the IoC container requires an explicit registration for concrete types
1 parent 2b2950c commit b256937

File tree

5 files changed

+158
-11
lines changed

5 files changed

+158
-11
lines changed

src/NHibernate.Test/CfgTest/SettingsFactoryFixture.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ public void DefaultValueForKeyWords()
3232
Assert.That(!settings.IsAutoQuoteEnabled);
3333
}
3434

35+
[Test]
36+
public void DefaultServicesWithExplicitServiceProvider()
37+
{
38+
Environment.ServiceProvider = new SimpleServiceProvider(true);
39+
DefaultServices();
40+
}
41+
3542
[Test]
3643
public void DefaultServices()
3744
{

src/NHibernate.Test/CfgTest/SimpleServiceProvider.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ public class SimpleServiceProvider : IServiceProvider
1111
{
1212
private readonly ConcurrentDictionary<System.Type, Func<object>> _registeredTypeProviders =
1313
new ConcurrentDictionary<System.Type, Func<object>>();
14+
private readonly bool _explicit;
15+
16+
public SimpleServiceProvider()
17+
{
18+
19+
}
20+
21+
public SimpleServiceProvider(bool @explicit)
22+
{
23+
_explicit = @explicit;
24+
}
1425

1526
/// <inheritdoc />
1627
public object GetService(System.Type serviceType)
@@ -25,7 +36,7 @@ public object GetService(System.Type serviceType)
2536
return serviceProvider();
2637
}
2738

28-
if (serviceType.IsInterface || serviceType.IsAbstract)
39+
if (_explicit || serviceType.IsInterface || serviceType.IsAbstract)
2940
{
3041
return null;
3142
}

src/NHibernate.Test/UtilityTest/PropertiesHelperTest.cs

Lines changed: 107 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using NHibernate.Bytecode;
44
using NHibernate.Connection;
5+
using NHibernate.Linq.Functions;
56
using NHibernate.Test.CfgTest;
67
using NHibernate.Util;
78
using NUnit.Framework;
@@ -58,6 +59,42 @@ public void GetInstanceByDefault()
5859
Assert.That(instance, Is.TypeOf<DebugConnectionProvider>());
5960
}
6061

62+
[Test]
63+
public void GetInstanceByDefaultNull()
64+
{
65+
var instance = PropertiesHelper.GetInstance<IConnectionProvider>(
66+
"conn",
67+
new Dictionary<string, string>(),
68+
null);
69+
Assert.That(instance, Is.Null);
70+
}
71+
72+
[Test]
73+
public void GetInstanceByDefaultWithExplicitServiceProvider()
74+
{
75+
Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true);
76+
var instance = PropertiesHelper.GetInstance<IConnectionProvider>(
77+
"conn",
78+
new Dictionary<string, string>(),
79+
typeof(DriverConnectionProvider));
80+
Assert.That(instance, Is.Not.Null);
81+
Assert.That(instance, Is.TypeOf<DriverConnectionProvider>());
82+
}
83+
84+
[Test]
85+
public void GetExternalInstanceByDefaultWithExplicitServiceProvider()
86+
{
87+
Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true);
88+
Assert.Throws<HibernateException>(
89+
() =>
90+
{
91+
PropertiesHelper.GetInstance<IConnectionProvider>(
92+
"conn",
93+
new Dictionary<string, string>(),
94+
typeof(DebugConnectionProvider));
95+
});
96+
}
97+
6198
[Test]
6299
public void GetInstanceByRegistration()
63100
{
@@ -77,12 +114,38 @@ public void GetInstanceByProperty()
77114
{
78115
var instance = PropertiesHelper.GetInstance<IConnectionProvider>(
79116
"conn",
80-
new Dictionary<string, string> {{ "conn", typeof(DriverConnectionProvider).AssemblyQualifiedName } },
117+
new Dictionary<string, string> {{"conn", typeof(DriverConnectionProvider).AssemblyQualifiedName}},
118+
typeof(DebugConnectionProvider));
119+
Assert.That(instance, Is.Not.Null);
120+
Assert.That(instance, Is.TypeOf<DriverConnectionProvider>());
121+
}
122+
123+
[Test]
124+
public void GetInstanceByPropertyWithExplicitServiceProvider()
125+
{
126+
Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true);
127+
var instance = PropertiesHelper.GetInstance<IConnectionProvider>(
128+
"conn",
129+
new Dictionary<string, string> {{"conn", typeof(DriverConnectionProvider).AssemblyQualifiedName}},
81130
typeof(DebugConnectionProvider));
82131
Assert.That(instance, Is.Not.Null);
83132
Assert.That(instance, Is.TypeOf<DriverConnectionProvider>());
84133
}
85134

135+
[Test]
136+
public void GetExternalInstanceByPropertyWithExplicitServiceProvider()
137+
{
138+
Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true);
139+
Assert.Throws<HibernateException>(
140+
() =>
141+
{
142+
PropertiesHelper.GetInstance<IConnectionProvider>(
143+
"conn",
144+
new Dictionary<string, string> {{"conn", typeof(DebugConnectionProvider).AssemblyQualifiedName}},
145+
typeof(DriverConnectionProvider));
146+
});
147+
}
148+
86149
[Test]
87150
public void GetInstanceByInvalidDefault()
88151
{
@@ -113,14 +176,55 @@ public void GetInstanceByInvalidRegistration()
113176
}
114177

115178
[Test]
116-
public void GetInstanceByInvalidProperty()
179+
public void GetInstanceByInvalidPropertyClassType()
180+
{
181+
Assert.Throws<HibernateException>(
182+
() =>
183+
{
184+
PropertiesHelper.GetInstance<IConnectionProvider>(
185+
"conn",
186+
new Dictionary<string, string> {{"conn", typeof(DefaultLinqToHqlGeneratorsRegistry).AssemblyQualifiedName}},
187+
typeof(DriverConnectionProvider));
188+
});
189+
}
190+
191+
[Test]
192+
public void GetInstanceByInvalidPropertyClassTypeWithExplicitServiceProvider()
193+
{
194+
Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true);
195+
Assert.Throws<HibernateException>(
196+
() =>
197+
{
198+
PropertiesHelper.GetInstance<IConnectionProvider>(
199+
"conn",
200+
new Dictionary<string, string> {{"conn", typeof(DefaultLinqToHqlGeneratorsRegistry).AssemblyQualifiedName}},
201+
typeof(DriverConnectionProvider));
202+
});
203+
}
204+
205+
[Test]
206+
public void GetInstanceByInvalidPropertyClassName()
207+
{
208+
Assert.Throws<HibernateException>(
209+
() =>
210+
{
211+
PropertiesHelper.GetInstance<IConnectionProvider>(
212+
"conn",
213+
new Dictionary<string, string> {{"conn", "test"}},
214+
typeof(DriverConnectionProvider));
215+
});
216+
}
217+
218+
[Test]
219+
public void GetInstanceByInvalidPropertyClassNameWithExplicitServiceProvider()
117220
{
221+
Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true);
118222
Assert.Throws<HibernateException>(
119223
() =>
120224
{
121225
PropertiesHelper.GetInstance<IConnectionProvider>(
122226
"conn",
123-
new Dictionary<string, string> {{"conn", typeof(PropertiesHelperTest).AssemblyQualifiedName}},
227+
new Dictionary<string, string> {{"conn", "test"}},
124228
typeof(DriverConnectionProvider));
125229
});
126230
}

src/NHibernate/Util/PropertiesHelper.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using NHibernate.Bytecode;
34
using NHibernate.Cfg;
45

56
namespace NHibernate.Util
@@ -95,10 +96,13 @@ public static TService GetInstance<TService>(
9596
System.Type type = null;
9697
try
9798
{
98-
type = className != null
99-
? ReflectHelper.ClassForName(className)
100-
: typeof(TService);
99+
if (className != null)
100+
{
101+
type = ReflectHelper.ClassForName(className);
102+
return (TService) Cfg.Environment.ServiceProvider.GetInstance(type);
103+
}
101104

105+
type = typeof(TService);
102106
var instance = (TService) Cfg.Environment.ServiceProvider.GetService(type);
103107
if (instance != null)
104108
{

src/NHibernate/Util/ServiceProviderExtensions.cs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using System;
2+
using System.Reflection;
23
using NHibernate.Bytecode;
34

45
namespace NHibernate.Util
56
{
67
internal static class ServiceProviderExtensions
78
{
9+
private static readonly string InternalAssemblyName = typeof(ServiceProviderExtensions).Assembly.GetName().ToString();
10+
811
/// <summary>
912
/// Get a service, throwing if it cannot be resolved.
1013
/// </summary>
@@ -18,11 +21,29 @@ public static object GetInstance(this IServiceProvider serviceProvider, System.T
1821
if (serviceType == null)
1922
throw new ArgumentNullException(nameof(serviceType));
2023
var service = serviceProvider.GetService(serviceType);
24+
if (service != null)
25+
{
26+
return service;
27+
}
28+
29+
// Some IoC containers require explicit registration for concete types. In order to avoid registering all NHibernate types
30+
// the Activator.CreateInstance is used for internal types, but the strictness is respected for external types.
31+
Exception innerException = null;
32+
if (serviceType.IsClass && !serviceType.IsAbstract && InternalAssemblyName.Equals(serviceType.Assembly.GetName().ToString()))
33+
{
34+
try
35+
{
36+
return Activator.CreateInstance(serviceType);
37+
}
38+
catch (Exception e)
39+
{
40+
innerException = e;
41+
}
42+
}
2143

22-
if (service == null)
23-
throw new HibernateServiceProviderException(
24-
$"Unable to resolve an instance for {serviceType.AssemblyQualifiedName}");
25-
return service;
44+
throw new HibernateServiceProviderException(
45+
$"Unable to resolve an instance for {serviceType.AssemblyQualifiedName}, " +
46+
"make sure that the service is registered and a non-null value is returned for it.", innerException);
2647
}
2748
}
2849
}

0 commit comments

Comments
 (0)