Skip to content

Ability to replace ConfigurationManager with a custom config provider #2116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Oct 16, 2019
6 changes: 2 additions & 4 deletions src/NHibernate.Test/Async/NHSpecificTest/NH2420/Fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
using System.Data.Common;
using System.Data.Odbc;
using System.Data.SqlClient;
using System.Configuration;
using System.Transactions;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Engine;
Expand Down Expand Up @@ -43,9 +43,7 @@ private string FetchConnectionStringFromConfiguration()
string connectionStringName;
if (cfg.Properties.TryGetValue(Environment.ConnectionStringName, out connectionStringName))
{
var connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
Assert.That(connectionStringSettings, Is.Not.Null);
connectionString = connectionStringSettings.ConnectionString;
connectionString = ConfigurationProvider.Current.GetNamedConnectionString(connectionStringName);
Assert.That(connectionString, Is.Not.Null.Or.Empty);
return connectionString;
}
Expand Down
13 changes: 2 additions & 11 deletions src/NHibernate.Test/CfgTest/ConfigurationSchemaFixture.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Configuration;
using NHibernate.Event;
using NUnit.Framework;
using NHibernate.Cfg;
Expand Down Expand Up @@ -26,9 +25,7 @@ public void SessionFactoryIsRequiredWhenConfigurationIsNotLoadedFromAppConfig()
[Test]
public void FromAppConfigTest()
{
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);

IHibernateConfiguration hc = ConfigurationManager.GetSection("hibernate-configuration") as IHibernateConfiguration;
IHibernateConfiguration hc = ConfigurationProvider.Current.GetConfiguration();
Assert.That(hc.ByteCodeProviderType, Is.EqualTo("lcg"));
Assert.IsTrue(hc.UseReflectionOptimizer);
Assert.AreEqual("NHibernate.Test", hc.SessionFactory.Name);
Expand All @@ -37,8 +34,6 @@ public void FromAppConfigTest()
[Test]
public void ByteCodeProvider()
{
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);

var xml =
@"<?xml version='1.0' encoding='utf-8' ?>
<hibernate-configuration xmlns='urn:nhibernate-configuration-2.2'>
Expand All @@ -54,9 +49,7 @@ public void ByteCodeProvider()
[Test]
public void IgnoreSystemOutOfAppConfig()
{
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);

IHibernateConfiguration hc = ConfigurationManager.GetSection("hibernate-configuration") as IHibernateConfiguration;
IHibernateConfiguration hc = ConfigurationProvider.Current.GetConfiguration();
string xml =
@"<?xml version='1.0' encoding='utf-8' ?>
<hibernate-configuration xmlns='urn:nhibernate-configuration-2.2'>
Expand All @@ -75,8 +68,6 @@ public void IgnoreSystemOutOfAppConfig()
[Test]
public void ObjectsFactory()
{
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);

var xml =
@"<?xml version='1.0' encoding='utf-8' ?>
<hibernate-configuration xmlns='urn:nhibernate-configuration-2.2'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ public void ConnectionStringInSettingsOverrideNamedConnectionSTring()
[Test]
public void CanGetNamedConnectionStringFromConfiguration()
{
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);

Dictionary<string, string> settings = new Dictionary<string, string>();
settings.Add(Environment.ConnectionStringName, "DummyConnectionString");
MockConnectionProvider cp = new MockConnectionProvider();
Expand Down
4 changes: 0 additions & 4 deletions src/NHibernate.Test/Logging/LoggerProviderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,13 @@ public void LoggerProviderCanCreateLoggers_Obsolete()
[Test]
public void WhenNotConfiguredAndLog4NetExistsThenUseLog4NetFactory()
{
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);

// NoLoggingNHibernateLogger is internal
Assert.That(NHibernateLogger.For("pizza").GetType().Name, Is.Not.EqualTo("NoLoggingNHibernateLogger"));
}

[Test, Obsolete]
public void WhenNotConfiguredAndLog4NetExistsThenUseLog4NetFactory_Obsolete()
{
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);

Assert.That(LoggerProvider.LoggerFor("pizza"), Is.Not.InstanceOf<NoLoggingInternalLogger>());

// works because this is the legacy provider with a legacy logger
Expand Down
6 changes: 2 additions & 4 deletions src/NHibernate.Test/NHSpecificTest/NH2420/Fixture.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Data.Common;
using System.Data.Odbc;
using System.Data.SqlClient;
using System.Configuration;
using System.Transactions;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Engine;
Expand Down Expand Up @@ -32,9 +32,7 @@ private string FetchConnectionStringFromConfiguration()
string connectionStringName;
if (cfg.Properties.TryGetValue(Environment.ConnectionStringName, out connectionStringName))
{
var connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
Assert.That(connectionStringSettings, Is.Not.Null);
connectionString = connectionStringSettings.ConnectionString;
connectionString = ConfigurationProvider.Current.GetNamedConnectionString(connectionStringName);
Assert.That(connectionString, Is.Not.Null.Or.Empty);
return connectionString;
}
Expand Down
25 changes: 6 additions & 19 deletions src/NHibernate.Test/TestsContext.cs
Original file line number Diff line number Diff line change
@@ -1,46 +1,33 @@
using NUnit.Framework;
#if NETCOREAPP2_0
using NUnit.Framework;

#if NETCOREAPP2_0
using System.Configuration;
using System.IO;
using log4net.Repository.Hierarchy;
using NHibernate.Cfg;
using NHibernate.Cfg.ConfigurationSchema;
#endif

namespace NHibernate.Test
{
#if NETCOREAPP2_0
[SetUpFixture]
#endif
public class TestsContext
{
public static bool ExecutingWithVsTest { get; } =
private static bool ExecutingWithVsTest { get; } =
System.Reflection.Assembly.GetEntryAssembly()?.GetName().Name == "testhost";

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

ConfigureLog4Net();
}

public static IHibernateConfiguration GetTestAssemblyHibernateConfiguration()
{
var assemblyPath =
Path.Combine(TestContext.CurrentContext.TestDirectory, Path.GetFileName(typeof(TestsContext).Assembly.Location));
var configuration = ConfigurationManager.OpenExeConfiguration(assemblyPath);
var section = configuration.GetSection(CfgXmlHelper.CfgSectionName);
return HibernateConfiguration.FromAppConfig(section.SectionInformation.GetRawXml());
}

private static void ConfigureLog4Net()
{
var hierarchy = (Hierarchy)log4net.LogManager.GetRepository(typeof(TestsContext).Assembly);
Expand All @@ -58,6 +45,6 @@ private static void ConfigureLog4Net()
hierarchy.Root.AddAppender(consoleAppender);
hierarchy.Configured = true;
}
#endif
}
}
#endif
1 change: 0 additions & 1 deletion src/NHibernate/Async/Connection/ConnectionProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

using System;
using System.Collections;
using System.Configuration;
using System.Data.Common;

using NHibernate.Driver;
Expand Down
13 changes: 13 additions & 0 deletions src/NHibernate/Cfg/AppSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace NHibernate.Cfg
{
/// <summary>
/// Configuration App Settings
/// </summary>
public static class AppSettings
{
/// <summary>
/// Type that implements <see cref="INHibernateLoggerFactory"/>
/// </summary>
public const string LoggerFactoryClassName = "nhibernate-logger";
}
}
29 changes: 29 additions & 0 deletions src/NHibernate/Cfg/ConfigurationProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace NHibernate.Cfg
{
/// <summary>
/// Base class for NHibernate configuration settings
/// </summary>
public abstract class ConfigurationProvider
{
private static ConfigurationProvider _current = new StaticConfigurationManagerProvider();

/// <summary>
/// Provides ability to override default <see cref="System.Configuration.ConfigurationManager"/> with custom implementation.
/// Can be set to null if all configuration is specified by code
/// </summary>
public static ConfigurationProvider Current
{
get => _current;
set => _current = value ?? new NullConfigurationProvider();
}

public abstract IHibernateConfiguration GetConfiguration();

public abstract string GetNamedConnectionString(string name);

/// <summary>
/// Type that implements <see cref="INHibernateLoggerFactory"/>
/// </summary>
public abstract string GetLoggerFactoryClassName();
}
}
26 changes: 5 additions & 21 deletions src/NHibernate/Cfg/Environment.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Reflection;

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

private static IHibernateConfiguration GetHibernateConfiguration()
{
object config = ConfigurationManager.GetSection(CfgXmlHelper.CfgSectionName);
if (config == null)
var nhConfig = ConfigurationProvider.Current.GetConfiguration();
if (nhConfig == null && log.IsInfoEnabled())
{
log.Info("{0} section not found in application configuration file", CfgXmlHelper.CfgSectionName);
return null;
}

var nhConfig = config as IHibernateConfiguration;
if (nhConfig == null)
{
log.Info(
"{0} section handler, in application configuration file, is not IHibernateConfiguration, section ignored",
CfgXmlHelper.CfgSectionName);
}

return nhConfig;
Expand Down Expand Up @@ -566,7 +556,6 @@ private static IObjectsFactory CreateCustomObjectsFactory(string assemblyQualifi
}
}


/// <summary>
/// Get a named connection string, if configured.
/// </summary>
Expand All @@ -576,18 +565,13 @@ private static IObjectsFactory CreateCustomObjectsFactory(string assemblyQualifi
/// </exception>
internal static string GetNamedConnectionString(IDictionary<string, string> settings)
{
string connStringName;
if (!settings.TryGetValue(ConnectionStringName, out connStringName))
if (!settings.TryGetValue(ConnectionStringName, out var connStringName))
return null;

ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[connStringName];
if (connectionStringSettings == null)
throw new HibernateException($"Could not find named connection string '{connStringName}'.");

return connectionStringSettings.ConnectionString;
return ConfigurationProvider.Current.GetNamedConnectionString(connStringName)
?? throw new HibernateException($"Could not find named connection string '{connStringName}'.");
}


/// <summary>
/// Get the configured connection string, from <see cref="ConnectionString"/> if that
/// is set, otherwise from <see cref="ConnectionStringName"/>, or null if that isn't
Expand Down
20 changes: 20 additions & 0 deletions src/NHibernate/Cfg/NullConfigurationProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace NHibernate.Cfg
{
class NullConfigurationProvider : ConfigurationProvider
{
public override IHibernateConfiguration GetConfiguration()
{
return null;
}

public override string GetNamedConnectionString(string name)
{
return null;
}

public override string GetLoggerFactoryClassName()
{
return null;
}
}
}
42 changes: 42 additions & 0 deletions src/NHibernate/Cfg/StaticConfigurationManagerProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Configuration;
using System.Linq;
using NHibernate.Cfg.ConfigurationSchema;

namespace NHibernate.Cfg
{
class StaticConfigurationManagerProvider : ConfigurationProvider
{
public override IHibernateConfiguration GetConfiguration()
{
//TODO 6.0: Throw if not null and not IHibernateConfiguration
return ConfigurationManager.GetSection(CfgXmlHelper.CfgSectionName) as IHibernateConfiguration;
}

public override string GetNamedConnectionString(string name)
{
return ConfigurationManager.ConnectionStrings[name]?.ConnectionString;
}

public override string GetLoggerFactoryClassName()
{
var name = AppSettings.LoggerFactoryClassName;
var value = ConfigurationManager.AppSettings[name];

//TODO 6.0: Return value right away. Don't do ignore case search and document it as possible breaking change.
if (value != null)
return value;

return GetAppSettingIgnoreCase(name);
}

//TODO 6.0: Remove it
private static string GetAppSettingIgnoreCase(string name)
{
var key = ConfigurationManager.AppSettings.Keys.Cast<string>().FirstOrDefault(k => name.Equals(k, StringComparison.OrdinalIgnoreCase));
return string.IsNullOrEmpty(key)
? null
: ConfigurationManager.AppSettings[key];
}
}
}
40 changes: 40 additions & 0 deletions src/NHibernate/Cfg/SystemConfigurationProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Configuration;
using NHibernate.Cfg.ConfigurationSchema;

namespace NHibernate.Cfg
{
/// <summary>
/// Configuration manager that supports user provided configuration
/// </summary>
public class SystemConfigurationProvider : ConfigurationProvider
{
private readonly System.Configuration.Configuration _configuration;

public SystemConfigurationProvider(System.Configuration.Configuration configuration)
{
_configuration = configuration;
}

public override IHibernateConfiguration GetConfiguration()
{
ConfigurationSection configurationSection = _configuration.GetSection(CfgXmlHelper.CfgSectionName);
var xml = configurationSection?.SectionInformation.GetRawXml();
return xml == null ? null : HibernateConfiguration.FromAppConfig(xml);
}

public override string GetNamedConnectionString(string name)
{
return _configuration.ConnectionStrings.ConnectionStrings[name]?.ConnectionString;
}

public override string GetLoggerFactoryClassName()
{
return GetAppSetting(AppSettings.LoggerFactoryClassName);
}

private string GetAppSetting(string name)
{
return _configuration.AppSettings.Settings[name]?.Value;
}
}
}
1 change: 0 additions & 1 deletion src/NHibernate/Connection/ConnectionProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections;
using System.Configuration;
using System.Data.Common;

using NHibernate.Driver;
Expand Down
Loading