Skip to content

Commit dceb7fa

Browse files
bahusoidhazzik
authored andcommitted
Ability to replace ConfigurationManager with a custom config provider (#2116)
- Introduced abstract class ConfigurationProvider exposed as ConfigurationProvider.Current. To skip all configuration calls (fix for Xamarin) just set it to null: ConfigurationProvider.Current = null; Fixes #2105
1 parent 23df8cd commit dceb7fa

15 files changed

+164
-77
lines changed

src/NHibernate.Test/Async/NHSpecificTest/NH2420/Fixture.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
using System.Data.Common;
1212
using System.Data.Odbc;
1313
using System.Data.SqlClient;
14-
using System.Configuration;
1514
using System.Transactions;
15+
using NHibernate.Cfg;
1616
using NHibernate.Dialect;
1717
using NHibernate.Driver;
1818
using NHibernate.Engine;
@@ -43,9 +43,7 @@ private string FetchConnectionStringFromConfiguration()
4343
string connectionStringName;
4444
if (cfg.Properties.TryGetValue(Environment.ConnectionStringName, out connectionStringName))
4545
{
46-
var connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
47-
Assert.That(connectionStringSettings, Is.Not.Null);
48-
connectionString = connectionStringSettings.ConnectionString;
46+
connectionString = ConfigurationProvider.Current.GetNamedConnectionString(connectionStringName);
4947
Assert.That(connectionString, Is.Not.Null.Or.Empty);
5048
return connectionString;
5149
}

src/NHibernate.Test/CfgTest/ConfigurationSchemaFixture.cs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Configuration;
21
using NHibernate.Event;
32
using NUnit.Framework;
43
using NHibernate.Cfg;
@@ -26,9 +25,7 @@ public void SessionFactoryIsRequiredWhenConfigurationIsNotLoadedFromAppConfig()
2625
[Test]
2726
public void FromAppConfigTest()
2827
{
29-
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);
30-
31-
IHibernateConfiguration hc = ConfigurationManager.GetSection("hibernate-configuration") as IHibernateConfiguration;
28+
IHibernateConfiguration hc = ConfigurationProvider.Current.GetConfiguration();
3229
Assert.That(hc.ByteCodeProviderType, Is.EqualTo("lcg"));
3330
Assert.IsTrue(hc.UseReflectionOptimizer);
3431
Assert.AreEqual("NHibernate.Test", hc.SessionFactory.Name);
@@ -37,8 +34,6 @@ public void FromAppConfigTest()
3734
[Test]
3835
public void ByteCodeProvider()
3936
{
40-
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);
41-
4237
var xml =
4338
@"<?xml version='1.0' encoding='utf-8' ?>
4439
<hibernate-configuration xmlns='urn:nhibernate-configuration-2.2'>
@@ -54,9 +49,7 @@ public void ByteCodeProvider()
5449
[Test]
5550
public void IgnoreSystemOutOfAppConfig()
5651
{
57-
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);
58-
59-
IHibernateConfiguration hc = ConfigurationManager.GetSection("hibernate-configuration") as IHibernateConfiguration;
52+
IHibernateConfiguration hc = ConfigurationProvider.Current.GetConfiguration();
6053
string xml =
6154
@"<?xml version='1.0' encoding='utf-8' ?>
6255
<hibernate-configuration xmlns='urn:nhibernate-configuration-2.2'>
@@ -75,8 +68,6 @@ public void IgnoreSystemOutOfAppConfig()
7568
[Test]
7669
public void ObjectsFactory()
7770
{
78-
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);
79-
8071
var xml =
8172
@"<?xml version='1.0' encoding='utf-8' ?>
8273
<hibernate-configuration xmlns='urn:nhibernate-configuration-2.2'>

src/NHibernate.Test/ConnectionStringTest/NamedConnectionStringFixture.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ public void ConnectionStringInSettingsOverrideNamedConnectionSTring()
3535
[Test]
3636
public void CanGetNamedConnectionStringFromConfiguration()
3737
{
38-
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);
39-
4038
Dictionary<string, string> settings = new Dictionary<string, string>();
4139
settings.Add(Environment.ConnectionStringName, "DummyConnectionString");
4240
MockConnectionProvider cp = new MockConnectionProvider();

src/NHibernate.Test/Logging/LoggerProviderTest.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,13 @@ public void LoggerProviderCanCreateLoggers_Obsolete()
2424
[Test]
2525
public void WhenNotConfiguredAndLog4NetExistsThenUseLog4NetFactory()
2626
{
27-
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);
28-
2927
// NoLoggingNHibernateLogger is internal
3028
Assert.That(NHibernateLogger.For("pizza").GetType().Name, Is.Not.EqualTo("NoLoggingNHibernateLogger"));
3129
}
3230

3331
[Test, Obsolete]
3432
public void WhenNotConfiguredAndLog4NetExistsThenUseLog4NetFactory_Obsolete()
3533
{
36-
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);
37-
3834
Assert.That(LoggerProvider.LoggerFor("pizza"), Is.Not.InstanceOf<NoLoggingInternalLogger>());
3935

4036
// works because this is the legacy provider with a legacy logger

src/NHibernate.Test/NHSpecificTest/NH2420/Fixture.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using System.Data.Common;
22
using System.Data.Odbc;
33
using System.Data.SqlClient;
4-
using System.Configuration;
54
using System.Transactions;
5+
using NHibernate.Cfg;
66
using NHibernate.Dialect;
77
using NHibernate.Driver;
88
using NHibernate.Engine;
@@ -32,9 +32,7 @@ private string FetchConnectionStringFromConfiguration()
3232
string connectionStringName;
3333
if (cfg.Properties.TryGetValue(Environment.ConnectionStringName, out connectionStringName))
3434
{
35-
var connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
36-
Assert.That(connectionStringSettings, Is.Not.Null);
37-
connectionString = connectionStringSettings.ConnectionString;
35+
connectionString = ConfigurationProvider.Current.GetNamedConnectionString(connectionStringName);
3836
Assert.That(connectionString, Is.Not.Null.Or.Empty);
3937
return connectionString;
4038
}

src/NHibernate.Test/TestsContext.cs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,33 @@
1-
using NUnit.Framework;
1+
#if NETCOREAPP2_0
2+
using NUnit.Framework;
23

3-
#if NETCOREAPP2_0
44
using System.Configuration;
55
using System.IO;
66
using log4net.Repository.Hierarchy;
77
using NHibernate.Cfg;
8-
using NHibernate.Cfg.ConfigurationSchema;
9-
#endif
108

119
namespace NHibernate.Test
1210
{
13-
#if NETCOREAPP2_0
1411
[SetUpFixture]
15-
#endif
1612
public class TestsContext
1713
{
18-
public static bool ExecutingWithVsTest { get; } =
14+
private static bool ExecutingWithVsTest { get; } =
1915
System.Reflection.Assembly.GetEntryAssembly()?.GetName().Name == "testhost";
2016

21-
#if NETCOREAPP2_0
2217
[OneTimeSetUp]
2318
public void RunBeforeAnyTests()
2419
{
2520
//When .NET Core App 2.0 tests run from VS/VSTest the entry assembly is "testhost.dll"
2621
//so we need to explicitly load the configuration
2722
if (ExecutingWithVsTest)
2823
{
29-
Environment.InitializeGlobalProperties(GetTestAssemblyHibernateConfiguration());
24+
var assemblyPath = Path.Combine(TestContext.CurrentContext.TestDirectory, Path.GetFileName(typeof(TestsContext).Assembly.Location));
25+
ConfigurationProvider.Current = new SystemConfigurationProvider(ConfigurationManager.OpenExeConfiguration(assemblyPath));
3026
}
3127

3228
ConfigureLog4Net();
3329
}
3430

35-
public static IHibernateConfiguration GetTestAssemblyHibernateConfiguration()
36-
{
37-
var assemblyPath =
38-
Path.Combine(TestContext.CurrentContext.TestDirectory, Path.GetFileName(typeof(TestsContext).Assembly.Location));
39-
var configuration = ConfigurationManager.OpenExeConfiguration(assemblyPath);
40-
var section = configuration.GetSection(CfgXmlHelper.CfgSectionName);
41-
return HibernateConfiguration.FromAppConfig(section.SectionInformation.GetRawXml());
42-
}
43-
4431
private static void ConfigureLog4Net()
4532
{
4633
var hierarchy = (Hierarchy)log4net.LogManager.GetRepository(typeof(TestsContext).Assembly);
@@ -58,6 +45,6 @@ private static void ConfigureLog4Net()
5845
hierarchy.Root.AddAppender(consoleAppender);
5946
hierarchy.Configured = true;
6047
}
61-
#endif
6248
}
6349
}
50+
#endif

src/NHibernate/Async/Connection/ConnectionProvider.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
using System;
1212
using System.Collections;
13-
using System.Configuration;
1413
using System.Data.Common;
1514

1615
using NHibernate.Driver;

src/NHibernate/Cfg/AppSettings.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace NHibernate.Cfg
2+
{
3+
/// <summary>
4+
/// Configuration App Settings
5+
/// </summary>
6+
public static class AppSettings
7+
{
8+
/// <summary>
9+
/// Type that implements <see cref="INHibernateLoggerFactory"/>
10+
/// </summary>
11+
public const string LoggerFactoryClassName = "nhibernate-logger";
12+
}
13+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace NHibernate.Cfg
2+
{
3+
/// <summary>
4+
/// Base class for NHibernate configuration settings
5+
/// </summary>
6+
public abstract class ConfigurationProvider
7+
{
8+
private static ConfigurationProvider _current = new StaticConfigurationManagerProvider();
9+
10+
/// <summary>
11+
/// Provides ability to override default <see cref="System.Configuration.ConfigurationManager"/> with custom implementation.
12+
/// Can be set to null if all configuration is specified by code
13+
/// </summary>
14+
public static ConfigurationProvider Current
15+
{
16+
get => _current;
17+
set => _current = value ?? new NullConfigurationProvider();
18+
}
19+
20+
public abstract IHibernateConfiguration GetConfiguration();
21+
22+
public abstract string GetNamedConnectionString(string name);
23+
24+
/// <summary>
25+
/// Type that implements <see cref="INHibernateLoggerFactory"/>
26+
/// </summary>
27+
public abstract string GetLoggerFactoryClassName();
28+
}
29+
}

src/NHibernate/Cfg/Environment.cs

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Configuration;
43
using System.Reflection;
54

65
using NHibernate.Bytecode;
@@ -382,19 +381,10 @@ public static void InitializeGlobalProperties(IHibernateConfiguration config)
382381

383382
private static IHibernateConfiguration GetHibernateConfiguration()
384383
{
385-
object config = ConfigurationManager.GetSection(CfgXmlHelper.CfgSectionName);
386-
if (config == null)
384+
var nhConfig = ConfigurationProvider.Current.GetConfiguration();
385+
if (nhConfig == null && log.IsInfoEnabled())
387386
{
388387
log.Info("{0} section not found in application configuration file", CfgXmlHelper.CfgSectionName);
389-
return null;
390-
}
391-
392-
var nhConfig = config as IHibernateConfiguration;
393-
if (nhConfig == null)
394-
{
395-
log.Info(
396-
"{0} section handler, in application configuration file, is not IHibernateConfiguration, section ignored",
397-
CfgXmlHelper.CfgSectionName);
398388
}
399389

400390
return nhConfig;
@@ -566,7 +556,6 @@ private static IObjectsFactory CreateCustomObjectsFactory(string assemblyQualifi
566556
}
567557
}
568558

569-
570559
/// <summary>
571560
/// Get a named connection string, if configured.
572561
/// </summary>
@@ -576,18 +565,13 @@ private static IObjectsFactory CreateCustomObjectsFactory(string assemblyQualifi
576565
/// </exception>
577566
internal static string GetNamedConnectionString(IDictionary<string, string> settings)
578567
{
579-
string connStringName;
580-
if (!settings.TryGetValue(ConnectionStringName, out connStringName))
568+
if (!settings.TryGetValue(ConnectionStringName, out var connStringName))
581569
return null;
582570

583-
ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[connStringName];
584-
if (connectionStringSettings == null)
585-
throw new HibernateException($"Could not find named connection string '{connStringName}'.");
586-
587-
return connectionStringSettings.ConnectionString;
571+
return ConfigurationProvider.Current.GetNamedConnectionString(connStringName)
572+
?? throw new HibernateException($"Could not find named connection string '{connStringName}'.");
588573
}
589574

590-
591575
/// <summary>
592576
/// Get the configured connection string, from <see cref="ConnectionString"/> if that
593577
/// is set, otherwise from <see cref="ConnectionStringName"/>, or null if that isn't
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace NHibernate.Cfg
2+
{
3+
class NullConfigurationProvider : ConfigurationProvider
4+
{
5+
public override IHibernateConfiguration GetConfiguration()
6+
{
7+
return null;
8+
}
9+
10+
public override string GetNamedConnectionString(string name)
11+
{
12+
return null;
13+
}
14+
15+
public override string GetLoggerFactoryClassName()
16+
{
17+
return null;
18+
}
19+
}
20+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using System.Configuration;
3+
using System.Linq;
4+
using NHibernate.Cfg.ConfigurationSchema;
5+
6+
namespace NHibernate.Cfg
7+
{
8+
class StaticConfigurationManagerProvider : ConfigurationProvider
9+
{
10+
public override IHibernateConfiguration GetConfiguration()
11+
{
12+
//TODO 6.0: Throw if not null and not IHibernateConfiguration
13+
return ConfigurationManager.GetSection(CfgXmlHelper.CfgSectionName) as IHibernateConfiguration;
14+
}
15+
16+
public override string GetNamedConnectionString(string name)
17+
{
18+
return ConfigurationManager.ConnectionStrings[name]?.ConnectionString;
19+
}
20+
21+
public override string GetLoggerFactoryClassName()
22+
{
23+
var name = AppSettings.LoggerFactoryClassName;
24+
var value = ConfigurationManager.AppSettings[name];
25+
26+
//TODO 6.0: Return value right away. Don't do ignore case search and document it as possible breaking change.
27+
if (value != null)
28+
return value;
29+
30+
return GetAppSettingIgnoreCase(name);
31+
}
32+
33+
//TODO 6.0: Remove it
34+
private static string GetAppSettingIgnoreCase(string name)
35+
{
36+
var key = ConfigurationManager.AppSettings.Keys.Cast<string>().FirstOrDefault(k => name.Equals(k, StringComparison.OrdinalIgnoreCase));
37+
return string.IsNullOrEmpty(key)
38+
? null
39+
: ConfigurationManager.AppSettings[key];
40+
}
41+
}
42+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Configuration;
2+
using NHibernate.Cfg.ConfigurationSchema;
3+
4+
namespace NHibernate.Cfg
5+
{
6+
/// <summary>
7+
/// Configuration manager that supports user provided configuration
8+
/// </summary>
9+
public class SystemConfigurationProvider : ConfigurationProvider
10+
{
11+
private readonly System.Configuration.Configuration _configuration;
12+
13+
public SystemConfigurationProvider(System.Configuration.Configuration configuration)
14+
{
15+
_configuration = configuration;
16+
}
17+
18+
public override IHibernateConfiguration GetConfiguration()
19+
{
20+
ConfigurationSection configurationSection = _configuration.GetSection(CfgXmlHelper.CfgSectionName);
21+
var xml = configurationSection?.SectionInformation.GetRawXml();
22+
return xml == null ? null : HibernateConfiguration.FromAppConfig(xml);
23+
}
24+
25+
public override string GetNamedConnectionString(string name)
26+
{
27+
return _configuration.ConnectionStrings.ConnectionStrings[name]?.ConnectionString;
28+
}
29+
30+
public override string GetLoggerFactoryClassName()
31+
{
32+
return GetAppSetting(AppSettings.LoggerFactoryClassName);
33+
}
34+
35+
private string GetAppSetting(string name)
36+
{
37+
return _configuration.AppSettings.Settings[name]?.Value;
38+
}
39+
}
40+
}

src/NHibernate/Connection/ConnectionProvider.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22
using System.Collections;
3-
using System.Configuration;
43
using System.Data.Common;
54

65
using NHibernate.Driver;

0 commit comments

Comments
 (0)