diff --git a/Tools/packages.config b/Tools/packages.config index 438a75071ab..0a0677ffb1e 100644 --- a/Tools/packages.config +++ b/Tools/packages.config @@ -7,7 +7,7 @@ - + diff --git a/src/NHibernate.Test/Async/SessionBuilder/Fixture.cs b/src/NHibernate.Test/Async/SessionBuilder/Fixture.cs index bebdb8fe084..0cd255eae26 100644 --- a/src/NHibernate.Test/Async/SessionBuilder/Fixture.cs +++ b/src/NHibernate.Test/Async/SessionBuilder/Fixture.cs @@ -189,51 +189,6 @@ private void CanSetFlushMode(T sb) where T : ISessionBuilder FlushMode.Always, FlushMode.Auto, FlushMode.Commit, FlushMode.Manual); } - [Test] - public async Task CanSetInterceptorAsync() - { - var sb = Sfi.WithOptions(); - await (CanSetInterceptorAsync(sb)); - using (var s = sb.OpenSession()) - { - await (CanSetInterceptorAsync(s.SessionWithOptions())); - } - } - - private Task CanSetInterceptorAsync(T sb) where T : ISessionBuilder - { - try - { - var sbType = sb.GetType().Name; - // Do not use .Instance here, we want another instance. - var interceptor = new EmptyInterceptor(); - var options = DebugSessionFactory.GetCreationOptions(sb); - - Assert.AreEqual(Sfi.Interceptor, options.SessionInterceptor, $"{sbType}: Initial value"); - var fsb = sb.Interceptor(interceptor); - Assert.AreEqual(interceptor, options.SessionInterceptor, $"{sbType}: After call with an interceptor"); - Assert.AreEqual(sb, fsb, $"{sbType}: Unexpected fluent return after call with an interceptor"); - - if (sb is ISharedSessionBuilder ssb) - { - var fssb = ssb.Interceptor(); - Assert.AreEqual(EmptyInterceptor.Instance, options.SessionInterceptor, $"{sbType}: After call with shared interceptor"); - Assert.AreEqual(sb, fssb, $"{sbType}: Unexpected fluent return on shared"); - } - - Assert.Throws(() => sb.Interceptor(null), $"{sbType}: After call with null"); - - fsb = sb.NoInterceptor(); - Assert.AreEqual(EmptyInterceptor.Instance, options.SessionInterceptor, $"{sbType}: After no call"); - Assert.AreEqual(sb, fsb, $"{sbType}: Unexpected fluent return after no call"); - return Task.CompletedTask; - } - catch (Exception ex) - { - return Task.FromException(ex); - } - } - private void CanSet(T sb, Func setter, Func getter, Func shared, V initialValue, params V[] values) where T : ISessionBuilder { diff --git a/src/NHibernate.Test/Bytecode/ActivatorObjectFactoryFixture.cs b/src/NHibernate.Test/Bytecode/ActivatorObjectFactoryFixture.cs index daba1084d9a..513b02ea34f 100644 --- a/src/NHibernate.Test/Bytecode/ActivatorObjectFactoryFixture.cs +++ b/src/NHibernate.Test/Bytecode/ActivatorObjectFactoryFixture.cs @@ -4,7 +4,7 @@ namespace NHibernate.Test.Bytecode { - [TestFixture] + [TestFixture, Obsolete] public class ActivatorObjectFactoryFixture { public class WithOutPublicParameterLessCtor diff --git a/src/NHibernate.Test/Bytecode/ActivatorServiceProviderFixture.cs b/src/NHibernate.Test/Bytecode/ActivatorServiceProviderFixture.cs new file mode 100644 index 00000000000..7fa3fb633c8 --- /dev/null +++ b/src/NHibernate.Test/Bytecode/ActivatorServiceProviderFixture.cs @@ -0,0 +1,41 @@ +using System; +using NHibernate.Bytecode; +using NUnit.Framework; + +namespace NHibernate.Test.Bytecode +{ + [TestFixture] + public class ActivatorServiceProviderFixture + { + public class WithOutPublicParameterLessCtor + { + public string Something { get; set; } + protected WithOutPublicParameterLessCtor() { } + + public WithOutPublicParameterLessCtor(string something) + { + Something = something; + } + } + + public class PublicParameterLessCtor + { + } + + protected virtual IServiceProvider GetServiceProvider() + { + return new ActivatorServiceProvider(); + } + + [Test] + public void CreateInstanceDefCtor() + { + var sp = GetServiceProvider(); + Assert.Throws(() => sp.GetService(null)); + Assert.Throws(() => sp.GetService(typeof(WithOutPublicParameterLessCtor))); + var instance = sp.GetService(typeof(PublicParameterLessCtor)); + Assert.That(instance, Is.Not.Null); + Assert.That(instance, Is.InstanceOf()); + } + } +} diff --git a/src/NHibernate.Test/CfgTest/ConfigurationSchemaFixture.cs b/src/NHibernate.Test/CfgTest/ConfigurationSchemaFixture.cs index 11c7a28d844..55e2bc33159 100644 --- a/src/NHibernate.Test/CfgTest/ConfigurationSchemaFixture.cs +++ b/src/NHibernate.Test/CfgTest/ConfigurationSchemaFixture.cs @@ -73,14 +73,14 @@ public void IgnoreSystemOutOfAppConfig() } [Test] - public void ObjectsFactory() + public void ServiceProvider() { Assume.That(TestsContext.ExecutingWithVsTest, Is.False); var xml = @" - + "; @@ -89,11 +89,11 @@ public void ObjectsFactory() using (var xtr = new XmlTextReader(xml, XmlNodeType.Document, null)) { hc = new HibernateConfiguration(xtr); - Assert.That(hc.ObjectsFactoryType, Is.Null); + Assert.That(hc.ServiceProviderType, Is.Null); } hc = HibernateConfiguration.FromAppConfig(xml); - Assert.That(hc.ObjectsFactoryType, Is.EqualTo("test")); + Assert.That(hc.ServiceProviderType, Is.EqualTo("test")); } [Test] diff --git a/src/NHibernate.Test/CfgTest/CustomObjectsFactoryTest.cs b/src/NHibernate.Test/CfgTest/CustomObjectsFactoryTest.cs deleted file mode 100644 index a1df5d19293..00000000000 --- a/src/NHibernate.Test/CfgTest/CustomObjectsFactoryTest.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using NHibernate.Bytecode; -using NUnit.Framework; -using Environment = NHibernate.Cfg.Environment; - -namespace NHibernate.Test.CfgTest -{ - [TestFixture] - public class CustomObjectsFactoryTest - { - private class MyObjectsFactory : IObjectsFactory - { - public object CreateInstance(System.Type type) - { - throw new NotImplementedException(); - } - - public object CreateInstance(System.Type type, bool nonPublic) - { - throw new NotImplementedException(); - } - - public object CreateInstance(System.Type type, params object[] ctorArgs) - { - throw new NotImplementedException(); - } - } - private class InvalidObjectsFactory - { - } - private class InvalidNoCtorObjectsFactory : MyObjectsFactory - { - public InvalidNoCtorObjectsFactory(string pizza) {} - } - - [Test] - public void WhenNoShortCutUsedThenCanBuildObjectsFactory() - { - var properties = new Dictionary { { Environment.PropertyBytecodeProvider, typeof(MyObjectsFactory).AssemblyQualifiedName } }; - Assert.That(() => Environment.BuildObjectsFactory(properties), Throws.Nothing); - } - - [Test] - public void WhenNoShortCutUsedThenCanBuildInstanceOfConfiguredObjectsFactory() - { - var properties = new Dictionary { { Environment.PropertyObjectsFactory, typeof(MyObjectsFactory).AssemblyQualifiedName } }; - Assert.That(Environment.BuildObjectsFactory(properties), Is.InstanceOf()); - } - - [Test] - public void WhenInvalidThenThrow() - { - var properties = new Dictionary { { Environment.PropertyObjectsFactory, typeof(InvalidObjectsFactory).AssemblyQualifiedName } }; - Assert.That(() => Environment.BuildObjectsFactory(properties), Throws.TypeOf()); - } - - [Test] - public void WhenNoDefaultCtorThenThrow() - { - var properties = new Dictionary { { Environment.PropertyObjectsFactory, typeof(InvalidNoCtorObjectsFactory).AssemblyQualifiedName } }; - Assert.That(() => Environment.BuildObjectsFactory(properties), Throws.TypeOf() - .And.InnerException.Message.Contains("constructor was not found")); - } - } -} diff --git a/src/NHibernate.Test/CfgTest/CustomServiceProviderTest.cs b/src/NHibernate.Test/CfgTest/CustomServiceProviderTest.cs new file mode 100644 index 00000000000..fe19faa2fd0 --- /dev/null +++ b/src/NHibernate.Test/CfgTest/CustomServiceProviderTest.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using NHibernate.Bytecode; +using NUnit.Framework; +using Environment = NHibernate.Cfg.Environment; + +namespace NHibernate.Test.CfgTest +{ + [TestFixture] + public class CustomServiceProviderTest + { + private class MyServiceProvider : IServiceProvider + { + public object GetService(System.Type serviceType) + { + throw new NotImplementedException(); + } + } + private class InvalidServiceProvider + { + } + private class InvalidNoCtorServiceProvider : MyServiceProvider + { + public InvalidNoCtorServiceProvider(string pizza) {} + } + + [Test] + public void WhenNoShortCutUsedThenCanBuildServiceProvider() + { + var properties = new Dictionary { { Environment.PropertyBytecodeProvider, typeof(MyServiceProvider).AssemblyQualifiedName } }; + Assert.That(() => Environment.BuildServiceProvider(properties), Throws.Nothing); + } + + [Test] + public void WhenNoShortCutUsedThenCanBuildInstanceOfConfiguredServiceProvider() + { + var properties = new Dictionary { { Environment.PropertyServiceProvider, typeof(MyServiceProvider).AssemblyQualifiedName } }; + Assert.That(Environment.BuildServiceProvider(properties), Is.InstanceOf()); + } + + [Test] + public void WhenInvalidThenThrow() + { + var properties = new Dictionary { { Environment.PropertyServiceProvider, typeof(InvalidServiceProvider).AssemblyQualifiedName } }; + Assert.That(() => Environment.BuildServiceProvider(properties), Throws.TypeOf()); + } + + [Test] + public void WhenNoDefaultCtorThenThrow() + { + var properties = new Dictionary { { Environment.PropertyServiceProvider, typeof(InvalidNoCtorServiceProvider).AssemblyQualifiedName } }; + Assert.That(() => Environment.BuildServiceProvider(properties), Throws.TypeOf() + .And.InnerException.Message.Contains("constructor was not found")); + } + } +} diff --git a/src/NHibernate.Test/CfgTest/SettingsFactoryFixture.cs b/src/NHibernate.Test/CfgTest/SettingsFactoryFixture.cs index 640eb45cf80..f9bc66f579c 100644 --- a/src/NHibernate.Test/CfgTest/SettingsFactoryFixture.cs +++ b/src/NHibernate.Test/CfgTest/SettingsFactoryFixture.cs @@ -1,6 +1,19 @@ +using System; using System.Collections.Generic; +using NHibernate.AdoNet; +using NHibernate.Bytecode; +using NHibernate.Cache; using NHibernate.Cfg; +using NHibernate.Connection; +using NHibernate.Exceptions; +using NHibernate.Hql; +using NHibernate.Hql.Ast.ANTLR; +using NHibernate.Linq.Functions; +using NHibernate.Linq.Visitors; +using NHibernate.Transaction; +using NSubstitute; using NUnit.Framework; +using Environment = NHibernate.Cfg.Environment; namespace NHibernate.Test.CfgTest { @@ -18,5 +31,128 @@ public void DefaultValueForKeyWords() Assert.That(settings.IsKeywordsImportEnabled); Assert.That(!settings.IsAutoQuoteEnabled); } + + [Test] + public void DefaultServicesWithExplicitServiceProvider() + { + Environment.ServiceProvider = new SimpleServiceProvider(true); + DefaultServices(); + } + + [Test] + public void DefaultServices() + { + var properties = new Dictionary + { + {Environment.Dialect, typeof(Dialect.PostgreSQL83Dialect).FullName}, + {Environment.UseQueryCache, "true"} + }; + var settings = new SettingsFactory().BuildSettings(properties); + Assert.That(settings.BatcherFactory, Is.TypeOf()); + Assert.That(settings.CacheProvider, Is.TypeOf()); + Assert.That(settings.ConnectionProvider, Is.TypeOf()); + Assert.That(settings.Dialect, Is.TypeOf()); + Assert.That(settings.LinqToHqlGeneratorsRegistry, Is.TypeOf()); + Assert.That(settings.QueryCacheFactory, Is.TypeOf()); + Assert.That(settings.QueryModelRewriterFactory, Is.Null); + Assert.That(settings.QueryTranslatorFactory, Is.TypeOf()); + Assert.That(settings.QueryCacheFactory, Is.TypeOf()); + Assert.That(settings.SqlExceptionConverter, Is.TypeOf()); + Assert.That(settings.TransactionFactory, Is.TypeOf()); + } + + [Test] + public void RegisteredServices() + { + var batcherFactory = Substitute.For(); + var cacheProvider = Substitute.For(); + var connectionProvider = Substitute.For(); + var dialect = new Dialect.MsSql2005Dialect(); + var linqToHqlRegistry = Substitute.For(); + var queryCacheFactory = Substitute.For(); + var queryModelRewriterFactory = Substitute.For(); + var queryTranslatorFactory = Substitute.For(); + var sqlExceptionConverter = Substitute.For(); + var transactionFactory = Substitute.For(); + + var sp = new SimpleServiceProvider(); + sp.Register(() => batcherFactory); + sp.Register(() => cacheProvider); + sp.Register(() => connectionProvider); + sp.Register(() => dialect); + sp.Register(() => linqToHqlRegistry); + sp.Register(() => queryCacheFactory); + sp.Register(() => queryModelRewriterFactory); + sp.Register(() => queryTranslatorFactory); + sp.Register(() => sqlExceptionConverter); + sp.Register(() => transactionFactory); + + Environment.ServiceProvider = sp; + + var properties = new Dictionary + { + {Environment.UseQueryCache, "true"} + }; + var settings = new SettingsFactory().BuildSettings(properties); + Assert.That(settings.BatcherFactory, Is.EqualTo(batcherFactory)); + Assert.That(settings.CacheProvider, Is.EqualTo(cacheProvider)); + Assert.That(settings.ConnectionProvider, Is.EqualTo(connectionProvider)); + Assert.That(settings.Dialect, Is.EqualTo(dialect)); + Assert.That(settings.LinqToHqlGeneratorsRegistry, Is.EqualTo(linqToHqlRegistry)); + Assert.That(settings.QueryCacheFactory, Is.EqualTo(queryCacheFactory)); + Assert.That(settings.QueryModelRewriterFactory, Is.EqualTo(queryModelRewriterFactory)); + Assert.That(settings.QueryTranslatorFactory, Is.EqualTo(queryTranslatorFactory)); + Assert.That(settings.SqlExceptionConverter, Is.EqualTo(sqlExceptionConverter)); + Assert.That(settings.TransactionFactory, Is.EqualTo(transactionFactory)); + } + + [Test] + public void InvalidRegisteredServices() + { + InvalidRegisteredService(); + InvalidRegisteredService(); + InvalidRegisteredService(); + InvalidRegisteredService(); + InvalidRegisteredService(); + InvalidRegisteredService(); + InvalidRegisteredService(); + InvalidRegisteredService(); + InvalidRegisteredService(); + } + + private void InvalidRegisteredService() + { + var sp = new SimpleServiceProvider(); + sp.Register(() => throw new InvalidOperationException()); + + Environment.ServiceProvider = sp; + + var properties = new Dictionary + { + {Environment.UseQueryCache, "true"} + }; + if (typeof(TService) != typeof(Dialect.Dialect)) + { + properties.Add(Environment.Dialect, typeof(Dialect.PostgreSQL83Dialect).FullName); + } + + Assert.Throws( + () => new SettingsFactory().BuildSettings(properties), + $"HibernateException should be thrown for service {typeof(TService)}"); + } + + private IServiceProvider _originalSp; + + [SetUp] + public void Setup() + { + _originalSp = Environment.ServiceProvider; + } + + [TearDown] + public void TearDown() + { + Environment.ServiceProvider = _originalSp; + } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/CfgTest/SimpleServiceProvider.cs b/src/NHibernate.Test/CfgTest/SimpleServiceProvider.cs new file mode 100644 index 00000000000..9d35f38de3b --- /dev/null +++ b/src/NHibernate.Test/CfgTest/SimpleServiceProvider.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NHibernate.Test.CfgTest +{ + public class SimpleServiceProvider : IServiceProvider + { + private readonly ConcurrentDictionary> _registeredTypeProviders = + new ConcurrentDictionary>(); + private readonly bool _explicit; + + public SimpleServiceProvider() + { + + } + + public SimpleServiceProvider(bool @explicit) + { + _explicit = @explicit; + } + + /// + public object GetService(System.Type serviceType) + { + if (serviceType == null) + { + throw new ArgumentNullException(nameof(serviceType)); + } + + if (_registeredTypeProviders.TryGetValue(serviceType, out var serviceProvider)) + { + return serviceProvider(); + } + + if (_explicit || serviceType.IsInterface || serviceType.IsAbstract) + { + return null; + } + + return Activator.CreateInstance(serviceType); + } + + /// + /// Register the specified delegate that will be called when the + /// type is requested. + /// + /// The type to register. + /// The delegate taht creates the instance. + public void Register(Func instanceCreator) + { + Register(typeof(TService), () => instanceCreator()); + } + + /// + /// Register the specified delegate that will be called when the + /// type is requested. + /// + /// The type to register. + /// The delegate that creates the instance. + public void Register(System.Type serviceType, Func instanceCreator) + { + if (serviceType == null) + { + throw new ArgumentNullException(nameof(serviceType)); + } + + if (instanceCreator == null) + { + throw new ArgumentNullException(nameof(instanceCreator)); + } + + if (!_registeredTypeProviders.TryAdd(serviceType, instanceCreator)) + { + throw new InvalidOperationException($"Service type {serviceType} is already registered."); + } + } + + /// + /// Register that an instance of will be returned when an + /// instance of type is requested. + /// + /// The type to register. + /// The concrete type that will be registered. + public void Register() where TImplementation : class + { + Register(typeof(TService), typeof(TImplementation)); + } + + /// + /// Register that an instance of will be returned when an + /// instance of type is requested. + /// + public void Register(System.Type serviceType, System.Type implementationType) + { + if (serviceType == null) + { + throw new ArgumentNullException(nameof(serviceType)); + } + if (implementationType == null) + { + throw new ArgumentNullException(nameof(implementationType)); + } + if (!serviceType.IsAssignableFrom(implementationType)) + { + throw new InvalidOperationException( + $"Implementation type {implementationType} is not assignable to service type {serviceType}."); + } + + if (implementationType.IsAbstract || implementationType.IsInterface) + { + throw new InvalidOperationException($"Implementation type {implementationType} is not a concrete type."); + } + + if (implementationType.GetConstructors().All(o => o.GetParameters().Length > 0)) + { + throw new InvalidOperationException($"Implementation type {implementationType} does not have a parameterless constructor."); + } + + Register(serviceType, () => Activator.CreateInstance(implementationType)); + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH1547/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH1547/Fixture.cs index 22267fb030c..383e0f85fdb 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1547/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1547/Fixture.cs @@ -132,7 +132,8 @@ public partial class DriverForSubstitutedCommand : IDriver public DriverForSubstitutedCommand() { - _driverImplementation = (IDriver) Cfg.Environment.ObjectsFactory.CreateInstance(DriverClass); + _driverImplementation = (IDriver) Cfg.Environment.ServiceProvider.GetService(DriverClass) ?? + throw new InvalidOperationException($"Driver {DriverClass} is not registered."); } DbCommand IDriver.GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes) diff --git a/src/NHibernate.Test/TypesTest/AbstractDateTimeTypeFixture.cs b/src/NHibernate.Test/TypesTest/AbstractDateTimeTypeFixture.cs index d04cc6693aa..d7082acdfde 100644 --- a/src/NHibernate.Test/TypesTest/AbstractDateTimeTypeFixture.cs +++ b/src/NHibernate.Test/TypesTest/AbstractDateTimeTypeFixture.cs @@ -534,7 +534,8 @@ public class ClientDriverWithParamsStats : IDriver public ClientDriverWithParamsStats() { - _driverImplementation = (IDriver) Cfg.Environment.ObjectsFactory.CreateInstance(DriverClass); + _driverImplementation = (IDriver) Cfg.Environment.ServiceProvider.GetService(DriverClass) ?? + throw new InvalidOperationException($"Driver {DriverClass} is not registered."); } private static void Inc(T type, IDictionary dic) diff --git a/src/NHibernate.Test/UtilityTest/PropertiesHelperTest.cs b/src/NHibernate.Test/UtilityTest/PropertiesHelperTest.cs index 188d6e9aef5..3b0087693bc 100644 --- a/src/NHibernate.Test/UtilityTest/PropertiesHelperTest.cs +++ b/src/NHibernate.Test/UtilityTest/PropertiesHelperTest.cs @@ -1,4 +1,9 @@ +using System; using System.Collections.Generic; +using NHibernate.Bytecode; +using NHibernate.Connection; +using NHibernate.Linq.Functions; +using NHibernate.Test.CfgTest; using NHibernate.Util; using NUnit.Framework; @@ -42,5 +47,196 @@ public void WhenValidInt64ValueThenValue() { Assert.That(PropertiesHelper.GetInt64("myProp", new Dictionary { { "myProp", long.MaxValue.ToString() } }, 5), Is.EqualTo(long.MaxValue)); } + + [Test] + public void GetInstanceByDefault() + { + var instance = PropertiesHelper.GetInstance( + "conn", + new Dictionary(), + typeof(DebugConnectionProvider)); + Assert.That(instance, Is.Not.Null); + Assert.That(instance, Is.TypeOf()); + } + + [Test] + public void GetInstanceByDefaultNull() + { + var instance = PropertiesHelper.GetInstance( + "conn", + new Dictionary(), + null); + Assert.That(instance, Is.Null); + } + + [Test] + public void GetInstanceByDefaultWithExplicitServiceProvider() + { + Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true); + var instance = PropertiesHelper.GetInstance( + "conn", + new Dictionary(), + typeof(DriverConnectionProvider)); + Assert.That(instance, Is.Not.Null); + Assert.That(instance, Is.TypeOf()); + } + + [Test] + public void GetExternalInstanceByDefaultWithExplicitServiceProvider() + { + Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true); + var instance = PropertiesHelper.GetInstance( + "conn", + new Dictionary(), + typeof(DebugConnectionProvider)); + Assert.That(instance, Is.Not.Null); + Assert.That(instance, Is.TypeOf()); + } + + [Test] + public void GetInstanceByRegistration() + { + var sp = new SimpleServiceProvider(); + sp.Register(); + Cfg.Environment.ServiceProvider = sp; + var instance = PropertiesHelper.GetInstance( + "conn", + new Dictionary(), + typeof(DebugConnectionProvider)); + Assert.That(instance, Is.Not.Null); + Assert.That(instance, Is.TypeOf()); + } + + [Test] + public void GetInstanceByProperty() + { + var instance = PropertiesHelper.GetInstance( + "conn", + new Dictionary {{"conn", typeof(DriverConnectionProvider).AssemblyQualifiedName}}, + typeof(DebugConnectionProvider)); + Assert.That(instance, Is.Not.Null); + Assert.That(instance, Is.TypeOf()); + } + + [Test] + public void GetInstanceByPropertyWithExplicitServiceProvider() + { + Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true); + var instance = PropertiesHelper.GetInstance( + "conn", + new Dictionary {{"conn", typeof(DriverConnectionProvider).AssemblyQualifiedName}}, + typeof(DebugConnectionProvider)); + Assert.That(instance, Is.Not.Null); + Assert.That(instance, Is.TypeOf()); + } + + [Test] + public void GetExternalInstanceByPropertyWithExplicitServiceProvider() + { + Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true); + var instance = PropertiesHelper.GetInstance( + "conn", + new Dictionary {{"conn", typeof(DebugConnectionProvider).AssemblyQualifiedName}}, + typeof(DriverConnectionProvider)); + Assert.That(instance, Is.Not.Null); + Assert.That(instance, Is.TypeOf()); + } + + [Test] + public void GetInstanceByInvalidDefault() + { + Assert.Throws( + () => + { + PropertiesHelper.GetInstance( + "conn", + new Dictionary(), + typeof(PropertiesHelperTest)); + }); + } + + [Test] + public void GetInstanceByInvalidRegistration() + { + var sp = new SimpleServiceProvider(); + sp.Register(typeof(IConnectionProvider), () => new PropertiesHelperTest()); + Cfg.Environment.ServiceProvider = sp; + Assert.Throws( + () => + { + PropertiesHelper.GetInstance( + "conn", + new Dictionary(), + typeof(DriverConnectionProvider)); + }); + } + + [Test] + public void GetInstanceByInvalidPropertyClassType() + { + Assert.Throws( + () => + { + PropertiesHelper.GetInstance( + "conn", + new Dictionary {{"conn", typeof(DefaultLinqToHqlGeneratorsRegistry).AssemblyQualifiedName}}, + typeof(DriverConnectionProvider)); + }); + } + + [Test] + public void GetInstanceByInvalidPropertyClassTypeWithExplicitServiceProvider() + { + Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true); + Assert.Throws( + () => + { + PropertiesHelper.GetInstance( + "conn", + new Dictionary {{"conn", typeof(DefaultLinqToHqlGeneratorsRegistry).AssemblyQualifiedName}}, + typeof(DriverConnectionProvider)); + }); + } + + [Test] + public void GetInstanceByInvalidPropertyClassName() + { + Assert.Throws( + () => + { + PropertiesHelper.GetInstance( + "conn", + new Dictionary {{"conn", "test"}}, + typeof(DriverConnectionProvider)); + }); + } + + [Test] + public void GetInstanceByInvalidPropertyClassNameWithExplicitServiceProvider() + { + Cfg.Environment.ServiceProvider = new SimpleServiceProvider(true); + Assert.Throws( + () => + { + PropertiesHelper.GetInstance( + "conn", + new Dictionary {{"conn", "test"}}, + typeof(DriverConnectionProvider)); + }); + } + + private IServiceProvider _originalSp; + + [SetUp] + public void Setup() + { + _originalSp = Cfg.Environment.ServiceProvider; + } + + [TearDown] + public void TearDown() + { + Cfg.Environment.ServiceProvider = _originalSp; + } } } diff --git a/src/NHibernate/Async/Tool/hbm2ddl/SchemaUpdate.cs b/src/NHibernate/Async/Tool/hbm2ddl/SchemaUpdate.cs index 893f48e9a57..7217a0d2b4c 100644 --- a/src/NHibernate/Async/Tool/hbm2ddl/SchemaUpdate.cs +++ b/src/NHibernate/Async/Tool/hbm2ddl/SchemaUpdate.cs @@ -78,7 +78,7 @@ public partial class SchemaUpdate { cfg.SetNamingStrategy( (INamingStrategy) - Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9)))); + Environment.ServiceProvider.GetMandatoryService(ReflectHelper.ClassForName(args[i].Substring(9)))); } } else diff --git a/src/NHibernate/Async/Tool/hbm2ddl/SchemaValidator.cs b/src/NHibernate/Async/Tool/hbm2ddl/SchemaValidator.cs index 78a3ead7995..4cf2c112f14 100644 --- a/src/NHibernate/Async/Tool/hbm2ddl/SchemaValidator.cs +++ b/src/NHibernate/Async/Tool/hbm2ddl/SchemaValidator.cs @@ -48,7 +48,7 @@ public partial class SchemaValidator { cfg.SetNamingStrategy( (INamingStrategy) - Cfg.Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9)))); + Cfg.Environment.ServiceProvider.GetMandatoryService(ReflectHelper.ClassForName(args[i].Substring(9)))); } } else diff --git a/src/NHibernate/Async/Type/CompositeCustomType.cs b/src/NHibernate/Async/Type/CompositeCustomType.cs index 10e6590f7a6..70bf795ce62 100644 --- a/src/NHibernate/Async/Type/CompositeCustomType.cs +++ b/src/NHibernate/Async/Type/CompositeCustomType.cs @@ -16,6 +16,7 @@ using NHibernate.Engine; using NHibernate.SqlTypes; using NHibernate.UserTypes; +using NHibernate.Util; using System.Collections.Generic; namespace NHibernate.Type diff --git a/src/NHibernate/Async/Type/CustomCollectionType.cs b/src/NHibernate/Async/Type/CustomCollectionType.cs index fa65efdd02d..e42987ab936 100644 --- a/src/NHibernate/Async/Type/CustomCollectionType.cs +++ b/src/NHibernate/Async/Type/CustomCollectionType.cs @@ -14,6 +14,7 @@ using NHibernate.Engine; using NHibernate.Persister.Collection; using NHibernate.UserTypes; +using NHibernate.Util; namespace NHibernate.Type { @@ -39,4 +40,4 @@ public override Task ReplaceElementsAsync(object original, object target } } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs b/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs index b112877c212..40be01625bb 100644 --- a/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs +++ b/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs @@ -6,6 +6,9 @@ namespace NHibernate.Bytecode { public abstract class AbstractBytecodeProvider : IBytecodeProvider, IInjectableProxyFactoryFactory, IInjectableCollectionTypeFactoryClass { +#pragma warning disable 618 + private static readonly IObjectsFactory ObjectFactory = new ActivatorObjectsFactory(); +#pragma warning restore 618 protected System.Type proxyFactoryFactory; private ICollectionTypeFactory collectionTypeFactory; private System.Type collectionTypeFactoryClass = typeof(Type.DefaultCollectionTypeFactory); @@ -20,7 +23,7 @@ public virtual IProxyFactoryFactory ProxyFactoryFactory { try { - return (IProxyFactoryFactory) Cfg.Environment.ObjectsFactory.CreateInstance(proxyFactoryFactory); + return (IProxyFactoryFactory) Cfg.Environment.ServiceProvider.GetMandatoryService(proxyFactoryFactory); } catch (Exception e) { @@ -35,8 +38,8 @@ public virtual IProxyFactoryFactory ProxyFactoryFactory public abstract IReflectionOptimizer GetReflectionOptimizer(System.Type clazz, IGetter[] getters, ISetter[] setters); // Since 5.2 - [Obsolete("Please use NHibernate.Cfg.Environment.ObjectsFactory instead")] - public virtual IObjectsFactory ObjectsFactory => Cfg.Environment.ObjectsFactory; + [Obsolete("Please use NHibernate.Cfg.Environment.ServiceProvider instead")] + public virtual IObjectsFactory ObjectsFactory => ObjectFactory; public virtual ICollectionTypeFactory CollectionTypeFactory { @@ -47,7 +50,7 @@ public virtual ICollectionTypeFactory CollectionTypeFactory try { collectionTypeFactory = - (ICollectionTypeFactory) Cfg.Environment.ObjectsFactory.CreateInstance(collectionTypeFactoryClass); + (ICollectionTypeFactory) Cfg.Environment.ServiceProvider.GetMandatoryService(collectionTypeFactoryClass); } catch (Exception e) { diff --git a/src/NHibernate/Bytecode/ActivatorObjectsFactory.cs b/src/NHibernate/Bytecode/ActivatorObjectsFactory.cs index 561d5b3afe4..d95016d65db 100644 --- a/src/NHibernate/Bytecode/ActivatorObjectsFactory.cs +++ b/src/NHibernate/Bytecode/ActivatorObjectsFactory.cs @@ -2,22 +2,20 @@ namespace NHibernate.Bytecode { - public class ActivatorObjectsFactory: IObjectsFactory + // Since v5.2 + [Obsolete("This type has no more usages and will be removed in a future version")] + public class ActivatorObjectsFactory : IObjectsFactory { public object CreateInstance(System.Type type) { return Activator.CreateInstance(type); } - // Since v5.2 - [Obsolete("This method has no more usages and will be removed in a future version")] public object CreateInstance(System.Type type, bool nonPublic) { return Activator.CreateInstance(type, nonPublic); } - // Since v5.2 - [Obsolete("This method has no more usages and will be removed in a future version")] public object CreateInstance(System.Type type, params object[] ctorArgs) { return Activator.CreateInstance(type, ctorArgs); diff --git a/src/NHibernate/Bytecode/ActivatorServiceProvider.cs b/src/NHibernate/Bytecode/ActivatorServiceProvider.cs new file mode 100644 index 00000000000..caa699bef5d --- /dev/null +++ b/src/NHibernate/Bytecode/ActivatorServiceProvider.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NHibernate.Bytecode +{ + /// + /// The default NHibernate service provider that uses to instantiate + /// services. + /// + public class ActivatorServiceProvider : IServiceProvider + { + /// + public object GetService(System.Type serviceType) + { + if (serviceType == null) + { + throw new ArgumentNullException(nameof(serviceType)); + } + + if (serviceType.IsInterface || serviceType.IsAbstract) + { + return null; + } + + return Activator.CreateInstance(serviceType); + } + } +} diff --git a/src/NHibernate/Bytecode/HibernateObjectsFactoryException.cs b/src/NHibernate/Bytecode/HibernateObjectsFactoryException.cs deleted file mode 100644 index f4551474bd0..00000000000 --- a/src/NHibernate/Bytecode/HibernateObjectsFactoryException.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace NHibernate.Bytecode -{ - /// - /// Thrown if NHibernate can't instantiate the type. - /// - [Serializable] - public class HibernateObjectsFactoryException : HibernateException - { - public HibernateObjectsFactoryException() {} - public HibernateObjectsFactoryException(string message) : base(message) {} - public HibernateObjectsFactoryException(string message, Exception inner) : base(message, inner) {} - - protected HibernateObjectsFactoryException(SerializationInfo info, StreamingContext context) : base(info, context) {} - } -} diff --git a/src/NHibernate/Bytecode/HibernateServiceProviderException.cs b/src/NHibernate/Bytecode/HibernateServiceProviderException.cs new file mode 100644 index 00000000000..a4570100059 --- /dev/null +++ b/src/NHibernate/Bytecode/HibernateServiceProviderException.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.Serialization; + +namespace NHibernate.Bytecode +{ + /// + /// Thrown if NHibernate can't instantiate the type. + /// + [Serializable] + public class HibernateServiceProviderException : HibernateException + { + public HibernateServiceProviderException() {} + public HibernateServiceProviderException(string message) : base(message) {} + public HibernateServiceProviderException(string message, Exception inner) : base(message, inner) {} + + protected HibernateServiceProviderException(SerializationInfo info, StreamingContext context) : base(info, context) {} + } +} diff --git a/src/NHibernate/Bytecode/IBytecodeProvider.cs b/src/NHibernate/Bytecode/IBytecodeProvider.cs index 2b9b4c29aa5..baffd17c7ec 100644 --- a/src/NHibernate/Bytecode/IBytecodeProvider.cs +++ b/src/NHibernate/Bytecode/IBytecodeProvider.cs @@ -28,7 +28,7 @@ public interface IBytecodeProvider /// For entities and its implementations. /// // Since 5.2 - [Obsolete("Please use NHibernate.Cfg.Environment.ObjectsFactory instead")] + [Obsolete("Please use NHibernate.Cfg.Environment.ServiceProvider instead")] IObjectsFactory ObjectsFactory { get; } /// @@ -48,4 +48,4 @@ public interface IBytecodeProvider // Not ported //ClassTransformer getTransformer(ClassFilter classFilter, FieldFilter fieldFilter); } -} \ No newline at end of file +} diff --git a/src/NHibernate/Bytecode/IObjectsFactory.cs b/src/NHibernate/Bytecode/IObjectsFactory.cs index 27a8ee26ec1..4f8b5b93288 100644 --- a/src/NHibernate/Bytecode/IObjectsFactory.cs +++ b/src/NHibernate/Bytecode/IObjectsFactory.cs @@ -5,6 +5,8 @@ namespace NHibernate.Bytecode /// /// Interface for instantiating NHibernate dependencies. /// + // Since v5.2 + [Obsolete("This type has no more usages and will be removed in a future version")] public interface IObjectsFactory { /// @@ -20,8 +22,6 @@ public interface IObjectsFactory /// The type of object to create. /// true if a public or nonpublic default constructor can match; false if only a public default constructor can match. /// A reference to the created object. - // Since v5.2 - [Obsolete("This method has no more usages and will be removed in a future version")] object CreateInstance(System.Type type, bool nonPublic); /// @@ -31,8 +31,6 @@ public interface IObjectsFactory /// The type of object to create. /// An array of constructor arguments. /// A reference to the created object. - // Since v5.2 - [Obsolete("This method has no more usages and will be removed in a future version")] object CreateInstance(System.Type type, params object[] ctorArgs); } } diff --git a/src/NHibernate/Cfg/Configuration.cs b/src/NHibernate/Cfg/Configuration.cs index 6e92eaf9f9f..18037115983 100644 --- a/src/NHibernate/Cfg/Configuration.cs +++ b/src/NHibernate/Cfg/Configuration.cs @@ -1908,7 +1908,7 @@ public void SetListeners(ListenerType type, string[] listenerClasses) { try { - listeners[i] = Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(listenerClasses[i])); + listeners[i] = Environment.ServiceProvider.GetMandatoryService(ReflectHelper.ClassForName(listenerClasses[i])); } catch (Exception e) { diff --git a/src/NHibernate/Cfg/ConfigurationSchema/CfgXmlHelper.cs b/src/NHibernate/Cfg/ConfigurationSchema/CfgXmlHelper.cs index d2cb08ecdd2..c4d5e8d1098 100644 --- a/src/NHibernate/Cfg/ConfigurationSchema/CfgXmlHelper.cs +++ b/src/NHibernate/Cfg/ConfigurationSchema/CfgXmlHelper.cs @@ -35,7 +35,7 @@ static CfgXmlHelper() nsMgr.AddNamespace(CfgNamespacePrefix, CfgSchemaXMLNS); ByteCodeProviderExpression = XPathExpression.Compile(RootPrefixPath + "bytecode-provider", nsMgr); - ObjectsFactoryExpression = XPathExpression.Compile(RootPrefixPath + "objects-factory", nsMgr); + ServiceProviderExpression = XPathExpression.Compile(RootPrefixPath + "service-provider", nsMgr); ReflectionOptimizerExpression = XPathExpression.Compile(RootPrefixPath + "reflection-optimizer", nsMgr); SessionFactoryExpression = XPathExpression.Compile(RootPrefixPath + "session-factory", nsMgr); SessionFactoryPropertiesExpression = XPathExpression.Compile(RootPrefixPath + "session-factory/" + ChildPrefixPath + "property", nsMgr); @@ -49,7 +49,7 @@ static CfgXmlHelper() /// XPath expression for bytecode-provider property. public static readonly XPathExpression ByteCodeProviderExpression; /// XPath expression for objects-factory property. - public static readonly XPathExpression ObjectsFactoryExpression; + public static readonly XPathExpression ServiceProviderExpression; /// XPath expression for reflection-optimizer property. public static readonly XPathExpression ReflectionOptimizerExpression; /// XPath expression for session-factory whole node. diff --git a/src/NHibernate/Cfg/ConfigurationSchema/HibernateConfiguration.cs b/src/NHibernate/Cfg/ConfigurationSchema/HibernateConfiguration.cs index 5208e7428e8..c3670f78899 100644 --- a/src/NHibernate/Cfg/ConfigurationSchema/HibernateConfiguration.cs +++ b/src/NHibernate/Cfg/ConfigurationSchema/HibernateConfiguration.cs @@ -77,7 +77,7 @@ private XmlReaderSettings GetSettings() private void Parse(XPathNavigator navigator, bool fromAppConfig) { ParseByteCodeProvider(navigator, fromAppConfig); - ParseObjectsFactory(navigator, fromAppConfig); + ParseServiceProvider(navigator, fromAppConfig); ParseReflectionOptimizer(navigator, fromAppConfig); XPathNavigator xpn = navigator.SelectSingleNode(CfgXmlHelper.SessionFactoryExpression); if (xpn != null) @@ -111,19 +111,19 @@ private void ParseByteCodeProvider(XPathNavigator navigator, bool fromAppConfig) } } - private void ParseObjectsFactory(XPathNavigator navigator, bool fromAppConfig) + private void ParseServiceProvider(XPathNavigator navigator, bool fromAppConfig) { - var xpn = navigator.SelectSingleNode(CfgXmlHelper.ObjectsFactoryExpression); + var xpn = navigator.SelectSingleNode(CfgXmlHelper.ServiceProviderExpression); if (xpn != null) { if (fromAppConfig) { xpn.MoveToFirstAttribute(); - ObjectsFactoryType = xpn.Value; + ServiceProviderType = xpn.Value; } else { - LogWarnIgnoredProperty("objects-factory"); + LogWarnIgnoredProperty("service-provider"); } } } @@ -166,7 +166,7 @@ public string ByteCodeProviderType /// /// Default value . // 6.0 TODO add to IHibernateConfiguration - public string ObjectsFactoryType { get; private set; } + public string ServiceProviderType { get; private set; } private bool useReflectionOptimizer = true; /// diff --git a/src/NHibernate/Cfg/Environment.cs b/src/NHibernate/Cfg/Environment.cs index 46121071367..6db6b0f23fd 100644 --- a/src/NHibernate/Cfg/Environment.cs +++ b/src/NHibernate/Cfg/Environment.cs @@ -202,9 +202,9 @@ public static string Version public const string PropertyUseReflectionOptimizer = "use_reflection_optimizer"; /// - /// Set the used to instantiate NHibernate's objects. + /// Set the used to instantiate NHibernate's objects. /// - public const string PropertyObjectsFactory = "objects_factory"; + public const string PropertyServiceProvider = "service_provider"; public const string UseProxyValidator = "use_proxy_validator"; public const string ProxyFactoryFactoryClass = "proxyfactory.factory_class"; @@ -313,7 +313,7 @@ public static void InitializeGlobalProperties(IHibernateConfiguration config) GlobalProperties[PropertyUseReflectionOptimizer] = config.UseReflectionOptimizer.ToString(); if (config is HibernateConfiguration nhConfig) { - GlobalProperties[PropertyObjectsFactory] = nhConfig.ObjectsFactoryType; + GlobalProperties[PropertyServiceProvider] = nhConfig.ServiceProviderType; } if (config.SessionFactory != null) { @@ -331,7 +331,7 @@ public static void InitializeGlobalProperties(IHibernateConfiguration config) VerifyProperties(GlobalProperties); BytecodeProviderInstance = BuildBytecodeProvider(GlobalProperties); - ObjectsFactory = BuildObjectsFactory(GlobalProperties); + ServiceProvider = BuildServiceProvider(GlobalProperties); EnableReflectionOptimizer = PropertiesHelper.GetBoolean(PropertyUseReflectionOptimizer, GlobalProperties); if (EnableReflectionOptimizer) @@ -391,12 +391,31 @@ public static IBytecodeProvider BytecodeProvider set { BytecodeProviderInstance = value; + // 6.0 TODO: remove following code. #pragma warning disable 618 var objectsFactory = BytecodeProviderInstance.ObjectsFactory; + if (objectsFactory != null && !(objectsFactory is ActivatorObjectsFactory)) + ServiceProvider = new ObjectsFactoryWrapper(objectsFactory); #pragma warning restore 618 - if (objectsFactory != null) - ObjectsFactory = objectsFactory; + } + } + + // Since its creation + [Obsolete("Transition class")] + private class ObjectsFactoryWrapper : IServiceProvider + { + private readonly IObjectsFactory _objectsFactory; + public ObjectsFactoryWrapper(IObjectsFactory objectsFactory) + { + _objectsFactory = objectsFactory; + } + + public object GetService(System.Type serviceType) + { + if (serviceType.IsAbstract || serviceType.IsInterface) + return null; + return _objectsFactory.CreateInstance(serviceType); } } @@ -413,7 +432,7 @@ public static IBytecodeProvider BytecodeProvider /// is created, otherwise the change may not take effect. /// For entities see and its implementations. /// - public static IObjectsFactory ObjectsFactory { get; set; } = new ActivatorObjectsFactory(); + public static IServiceProvider ServiceProvider { get; set; } = new ActivatorServiceProvider(); /// /// Whether to enable the use of reflection optimizer @@ -454,20 +473,17 @@ private static IBytecodeProvider BuildBytecodeProvider(string providerName) } } - public static IObjectsFactory BuildObjectsFactory(IDictionary properties) + public static IServiceProvider BuildServiceProvider(IDictionary properties) { - var typeAssemblyQualifiedName = PropertiesHelper.GetString(PropertyObjectsFactory, properties, null); + var typeAssemblyQualifiedName = PropertiesHelper.GetString(PropertyServiceProvider, properties, null); if (typeAssemblyQualifiedName == null) { - // 6.0 TODO: use default value of ObjectsFactory property -#pragma warning disable 618 - var objectsFactory = BytecodeProvider.ObjectsFactory ?? ObjectsFactory; -#pragma warning restore 618 - log.Info("Objects factory class : {0}", objectsFactory.GetType()); - return objectsFactory; + var serviceProvider = new ActivatorServiceProvider(); + log.Info("Service provider class : {0}", serviceProvider.GetType()); + return serviceProvider; } - log.Info("Custom objects factory class : {0}", typeAssemblyQualifiedName); - return CreateCustomObjectsFactory(typeAssemblyQualifiedName); + log.Info("Custom service provider class : {0}", typeAssemblyQualifiedName); + return CreateCustomServiceProvider(typeAssemblyQualifiedName); } private static IBytecodeProvider CreateCustomBytecodeProvider(string assemblyQualifiedName) @@ -498,31 +514,31 @@ private static IBytecodeProvider CreateCustomBytecodeProvider(string assemblyQua } } - private static IObjectsFactory CreateCustomObjectsFactory(string assemblyQualifiedName) + private static IServiceProvider CreateCustomServiceProvider(string assemblyQualifiedName) { try { var type = ReflectHelper.ClassForName(assemblyQualifiedName); try { - return (IObjectsFactory) Activator.CreateInstance(type); + return (IServiceProvider) Activator.CreateInstance(type); } catch (MissingMethodException ex) { - throw new HibernateObjectsFactoryException("Public constructor was not found for " + type, ex); + throw new HibernateServiceProviderException("Public constructor was not found for " + type, ex); } catch (InvalidCastException ex) { - throw new HibernateObjectsFactoryException(type + "Type does not implement " + typeof(IObjectsFactory), ex); + throw new HibernateServiceProviderException(type + "Type does not implement " + typeof(IServiceProvider), ex); } catch (Exception ex) { - throw new HibernateObjectsFactoryException("Unable to instantiate: " + type, ex); + throw new HibernateServiceProviderException("Unable to instantiate: " + type, ex); } } catch (Exception e) { - throw new HibernateObjectsFactoryException("Unable to create the instance of objects factory; check inner exception for detail", e); + throw new HibernateServiceProviderException("Unable to create the instance of service provider; check inner exception for detail", e); } } diff --git a/src/NHibernate/Cfg/SettingsFactory.cs b/src/NHibernate/Cfg/SettingsFactory.cs index dd3195350c4..373c2b61496 100644 --- a/src/NHibernate/Cfg/SettingsFactory.cs +++ b/src/NHibernate/Cfg/SettingsFactory.cs @@ -24,7 +24,7 @@ namespace NHibernate.Cfg public sealed class SettingsFactory { private static readonly INHibernateLogger log = NHibernateLogger.For(typeof(SettingsFactory)); - private static readonly string DefaultCacheProvider = typeof(NoCacheProvider).AssemblyQualifiedName; + private static readonly System.Type DefaultCacheProvider = typeof(NoCacheProvider); public Settings BuildSettings(IDictionary properties) { @@ -210,19 +210,11 @@ public Settings BuildSettings(IDictionary properties) if (useQueryCache) { - string queryCacheFactoryClassName = PropertiesHelper.GetString(Environment.QueryCacheFactory, properties, - typeof (StandardQueryCacheFactory).FullName); - log.Info("query cache factory: {0}", queryCacheFactoryClassName); - try - { - settings.QueryCacheFactory = - (IQueryCacheFactory) - Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(queryCacheFactoryClassName)); - } - catch (Exception cnfe) - { - throw new HibernateException("could not instantiate IQueryCacheFactory: " + queryCacheFactoryClassName, cnfe); - } + settings.QueryCacheFactory = PropertiesHelper.GetInstance( + Environment.QueryCacheFactory, + properties, + typeof(StandardQueryCacheFactory)); + log.Info("query cache factory: {0}", settings.QueryCacheFactory.GetType().AssemblyQualifiedName); } string sessionFactoryName = PropertiesHelper.GetString(Environment.SessionFactoryName, properties, null); @@ -312,31 +304,42 @@ public Settings BuildSettings(IDictionary properties) private static IBatcherFactory CreateBatcherFactory(IDictionary properties, int batchSize, IConnectionProvider connectionProvider) { - System.Type tBatcher = typeof (NonBatchingBatcherFactory); - string batcherClass = PropertiesHelper.GetString(Environment.BatchStrategy, properties, null); + System.Type tBatcher = null; + var batcherClass = PropertiesHelper.GetString(Environment.BatchStrategy, properties, null); if (string.IsNullOrEmpty(batcherClass)) { if (batchSize > 0) { // try to get the BatcherFactory from the Drive if not available use NonBatchingBatcherFactory - IEmbeddedBatcherFactoryProvider ebfp = connectionProvider.Driver as IEmbeddedBatcherFactoryProvider; - if (ebfp != null && ebfp.BatcherFactoryClass != null) + if (connectionProvider.Driver is IEmbeddedBatcherFactoryProvider ebfp && ebfp.BatcherFactoryClass != null) + { tBatcher = ebfp.BatcherFactoryClass; + } } } else { tBatcher = ReflectHelper.ClassForName(batcherClass); } - log.Info("Batcher factory: {0}", tBatcher.AssemblyQualifiedName); + + IBatcherFactory instance = null; try { - return (IBatcherFactory) Environment.ObjectsFactory.CreateInstance(tBatcher); + if (tBatcher == null) + { + instance = (IBatcherFactory) Environment.ServiceProvider.GetService(typeof(IBatcherFactory)); + } + if (instance == null) + { + instance = (IBatcherFactory) Environment.ServiceProvider.GetMandatoryService(tBatcher ?? typeof(NonBatchingBatcherFactory)); + } } catch (Exception cnfe) { throw new HibernateException("Could not instantiate BatcherFactory: " + batcherClass, cnfe); } + log.Info("Batcher factory: {0}", instance.GetType().AssemblyQualifiedName); + return instance; } private static string EnabledDisabled(bool value) @@ -346,36 +349,23 @@ private static string EnabledDisabled(bool value) private static ICacheProvider CreateCacheProvider(IDictionary properties) { - string cacheClassName = PropertiesHelper.GetString(Environment.CacheProvider, properties, DefaultCacheProvider); - log.Info("cache provider: {0}", cacheClassName); - try - { - return - (ICacheProvider) - Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(cacheClassName)); - } - catch (Exception e) - { - throw new HibernateException("could not instantiate CacheProvider: " + cacheClassName, e); - } + var instance = PropertiesHelper.GetInstance( + Environment.CacheProvider, + properties, + DefaultCacheProvider); + log.Info("cache provider: {0}", instance.GetType().AssemblyQualifiedName); + return instance; } // visibility changed and static modifier added until complete H3.2 porting of SettingsFactory private static IQueryTranslatorFactory CreateQueryTranslatorFactory(IDictionary properties) { - string className = PropertiesHelper.GetString( - Environment.QueryTranslator, properties, typeof(Hql.Ast.ANTLR.ASTQueryTranslatorFactory).FullName); - log.Info("Query translator: {0}", className); - try - { - return - (IQueryTranslatorFactory) - Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(className)); - } - catch (Exception cnfe) - { - throw new HibernateException("could not instantiate QueryTranslatorFactory: " + className, cnfe); - } + var instance = PropertiesHelper.GetInstance( + Environment.QueryTranslator, + properties, + typeof(Hql.Ast.ANTLR.ASTQueryTranslatorFactory)); + log.Info("Query translator: {0}", instance.GetType().AssemblyQualifiedName); + return instance; } private static System.Type CreateLinqQueryProviderType(IDictionary properties) @@ -395,43 +385,23 @@ private static System.Type CreateLinqQueryProviderType(IDictionary properties) { - string className = PropertiesHelper.GetString( - Environment.TransactionStrategy, properties, typeof(AdoNetWithSystemTransactionFactory).FullName); - log.Info("Transaction factory: {0}", className); - - try - { - var transactionFactory = - (ITransactionFactory) - Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(className)); - transactionFactory.Configure(properties); - return transactionFactory; - } - catch (Exception cnfe) - { - throw new HibernateException("could not instantiate TransactionFactory: " + className, cnfe); - } + var instance = PropertiesHelper.GetInstance( + Environment.TransactionStrategy, + properties, + typeof(AdoNetWithSystemTransactionFactory)); + instance.Configure(properties); + log.Info("Transaction factory: {0}", instance.GetType().AssemblyQualifiedName); + return instance; } private static IQueryModelRewriterFactory CreateQueryModelRewriterFactory(IDictionary properties) { - string className = PropertiesHelper.GetString(Environment.QueryModelRewriterFactory, properties, null); - - if (className == null) - return null; - - log.Info("Query model rewriter factory factory: {0}", className); - - try - { - return - (IQueryModelRewriterFactory) - Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(className)); - } - catch (Exception cnfe) - { - throw new HibernateException("could not instantiate IQueryModelRewriterFactory: " + className, cnfe); - } + var instance = PropertiesHelper.GetInstance( + Environment.QueryModelRewriterFactory, + properties, + null); + log.Info("Query model rewriter factory factory: '{0}'", instance?.GetType().AssemblyQualifiedName ?? "none"); + return instance; } } } diff --git a/src/NHibernate/Cfg/XmlHbmBinding/AuxiliaryDatabaseObjectFactory.cs b/src/NHibernate/Cfg/XmlHbmBinding/AuxiliaryDatabaseObjectFactory.cs index c6cb90ef954..7f55641b7e2 100644 --- a/src/NHibernate/Cfg/XmlHbmBinding/AuxiliaryDatabaseObjectFactory.cs +++ b/src/NHibernate/Cfg/XmlHbmBinding/AuxiliaryDatabaseObjectFactory.cs @@ -42,7 +42,7 @@ private static IAuxiliaryDatabaseObject CreateCustomObject(Mappings mappings, Hb System.Type customType = ReflectHelper.ClassForName(className); IAuxiliaryDatabaseObject customObject = - (IAuxiliaryDatabaseObject) Environment.ObjectsFactory.CreateInstance(customType); + (IAuxiliaryDatabaseObject) Environment.ServiceProvider.GetMandatoryService(customType); foreach (string dialectName in databaseObjectSchema.FindDialectScopeNames()) { diff --git a/src/NHibernate/Connection/ConnectionProvider.cs b/src/NHibernate/Connection/ConnectionProvider.cs index 0d908f1f672..6c0878be702 100644 --- a/src/NHibernate/Connection/ConnectionProvider.cs +++ b/src/NHibernate/Connection/ConnectionProvider.cs @@ -94,25 +94,16 @@ protected virtual string GetNamedConnectionString(IDictionary se /// protected virtual void ConfigureDriver(IDictionary settings) { - string driverClass; - if (!settings.TryGetValue(Environment.ConnectionDriver, out driverClass)) - { - throw new HibernateException("The " + Environment.ConnectionDriver + - " must be specified in the NHibernate configuration section."); - } - else - { - try - { - driver = - (IDriver) Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(driverClass)); - driver.Configure(settings); - } - catch (Exception e) - { - throw new HibernateException("Could not create the driver from " + driverClass + ".", e); - } - } + driver = PropertiesHelper.GetInstance( + Environment.ConnectionDriver, + settings, + null); + if (driver == null) + throw new HibernateException( + $"The {Environment.ConnectionDriver} must be specified in the NHibernate configuration section," + + "or Environment.ServiceProvider must be setup in order to resolve it."); + + driver.Configure(settings); } /// diff --git a/src/NHibernate/Connection/ConnectionProviderFactory.cs b/src/NHibernate/Connection/ConnectionProviderFactory.cs index b950389dfc8..9c6a71fb341 100644 --- a/src/NHibernate/Connection/ConnectionProviderFactory.cs +++ b/src/NHibernate/Connection/ConnectionProviderFactory.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using NHibernate.Util; @@ -13,37 +12,20 @@ public static class ConnectionProviderFactory { private static readonly INHibernateLogger log = NHibernateLogger.For(typeof(ConnectionProviderFactory)); - // cannot be instantiated public static IConnectionProvider NewConnectionProvider(IDictionary settings) { - IConnectionProvider connections; - string providerClass; - if (settings.TryGetValue(Environment.ConnectionProvider, out providerClass)) - { - try - { - log.Info("Initializing connection provider: {0}", providerClass); - connections = - (IConnectionProvider) - Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(providerClass)); - } - catch (Exception e) - { - log.Fatal(e, "Could not instantiate connection provider"); - throw new HibernateException("Could not instantiate connection provider: " + providerClass, e); - } - } - else if (settings.ContainsKey(Environment.ConnectionString) || settings.ContainsKey(Environment.ConnectionStringName)) - { - connections = new DriverConnectionProvider(); - } - else - { - log.Info("No connection provider specified, UserSuppliedConnectionProvider will be used."); - connections = new UserSuppliedConnectionProvider(); - } - connections.Configure(settings); - return connections; + var defaultConnectionProvider = + settings.ContainsKey(Environment.ConnectionString) || + settings.ContainsKey(Environment.ConnectionStringName) + ? typeof(DriverConnectionProvider) + : typeof(UserSuppliedConnectionProvider); + var connectionProvider = PropertiesHelper.GetInstance( + Environment.ConnectionProvider, + settings, + defaultConnectionProvider); + log.Info("Connection provider: '{0}'", connectionProvider.GetType().AssemblyQualifiedName); + connectionProvider.Configure(settings); + return connectionProvider; } } } diff --git a/src/NHibernate/Context/ICurrentSessionContext.cs b/src/NHibernate/Context/ICurrentSessionContext.cs index a2970da92f4..457b175a1cf 100644 --- a/src/NHibernate/Context/ICurrentSessionContext.cs +++ b/src/NHibernate/Context/ICurrentSessionContext.cs @@ -1,3 +1,4 @@ +using System; using NHibernate.Bytecode; using NHibernate.Engine; @@ -46,7 +47,7 @@ public interface ICurrentSessionContext /// /// An allowing to set its session factory. Implementing - /// this interface allows the to be used for instantiating the + /// this interface allows the to be used for instantiating the /// session context. /// public interface ISessionFactoryAwareCurrentSessionContext : ICurrentSessionContext diff --git a/src/NHibernate/Dialect/Dialect.cs b/src/NHibernate/Dialect/Dialect.cs index 1dcdac383f0..93577b7ffbd 100644 --- a/src/NHibernate/Dialect/Dialect.cs +++ b/src/NHibernate/Dialect/Dialect.cs @@ -146,16 +146,7 @@ protected Dialect() /// The specified Dialect public static Dialect GetDialect() { - string dialectName; - try - { - dialectName = Environment.Properties[Environment.Dialect]; - } - catch (Exception e) - { - throw new HibernateException("The dialect was not set. Set the property 'dialect'.", e); - } - return InstantiateDialect(dialectName, Environment.Properties); + return GetDialect(Environment.Properties); } /// @@ -169,29 +160,19 @@ public static Dialect GetDialect(IDictionary props) { if (props == null) throw new ArgumentNullException(nameof(props)); - string dialectName; - if (props.TryGetValue(Environment.Dialect, out dialectName) == false) + if (props.TryGetValue(Environment.Dialect, out var dialectName) && dialectName == null) + props = Environment.Properties; + + var dialect = PropertiesHelper.GetInstance( + Environment.Dialect, + props, + null); + + if (dialect == null) throw new InvalidOperationException("Could not find the dialect in the configuration"); - if (dialectName == null) - { - return GetDialect(); - } - return InstantiateDialect(dialectName, props); - } - - private static Dialect InstantiateDialect(string dialectName, IDictionary props) - { - try - { - var dialect = (Dialect)Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(dialectName)); - dialect.Configure(props); - return dialect; - } - catch (Exception e) - { - throw new HibernateException("Could not instantiate dialect class " + dialectName, e); - } + dialect.Configure(props); + return dialect; } /// diff --git a/src/NHibernate/Driver/ReflectionDriveConnectionCommandProvider.cs b/src/NHibernate/Driver/ReflectionDriveConnectionCommandProvider.cs index 4d007ba96fb..5bff9350740 100644 --- a/src/NHibernate/Driver/ReflectionDriveConnectionCommandProvider.cs +++ b/src/NHibernate/Driver/ReflectionDriveConnectionCommandProvider.cs @@ -1,5 +1,6 @@ using System; using System.Data.Common; +using NHibernate.Util; using Environment = NHibernate.Cfg.Environment; namespace NHibernate.Driver @@ -27,14 +28,14 @@ public ReflectionDriveConnectionCommandProvider(System.Type connectionType, Syst public DbConnection CreateConnection() { - return (DbConnection) Environment.ObjectsFactory.CreateInstance(connectionType); + return (DbConnection) Environment.ServiceProvider.GetMandatoryService(connectionType); } public DbCommand CreateCommand() { - return (DbCommand) Environment.ObjectsFactory.CreateInstance(commandType); + return (DbCommand) Environment.ServiceProvider.GetMandatoryService(commandType); } #endregion } -} \ No newline at end of file +} diff --git a/src/NHibernate/Exceptions/SQLExceptionConverterFactory.cs b/src/NHibernate/Exceptions/SQLExceptionConverterFactory.cs index 4bf6bfb52ba..3bce760d37d 100644 --- a/src/NHibernate/Exceptions/SQLExceptionConverterFactory.cs +++ b/src/NHibernate/Exceptions/SQLExceptionConverterFactory.cs @@ -37,12 +37,22 @@ public static ISQLExceptionConverter BuildSQLExceptionConverter(Dialect.Dialect { ISQLExceptionConverter converter = null; - string converterClassName; - properties.TryGetValue(Cfg.Environment.SqlExceptionConverter, out converterClassName); + properties.TryGetValue(Cfg.Environment.SqlExceptionConverter, out var converterClassName); if (!string.IsNullOrEmpty(converterClassName)) { converter = ConstructConverter(converterClassName, dialect.ViolatedConstraintNameExtracter); } + else + { + try + { + converter = (ISQLExceptionConverter) Cfg.Environment.ServiceProvider.GetService(typeof(ISQLExceptionConverter)); + } + catch (Exception t) + { + log.Warn(t, "Unable to construct instance of specified SQLExceptionConverter"); + } + } if (converter == null) { @@ -105,7 +115,7 @@ private static ISQLExceptionConverter ConstructConverter(string converterClassNa } // Otherwise, try to use the no-arg constructor - return (ISQLExceptionConverter) Cfg.Environment.ObjectsFactory.CreateInstance(converterClass); + return (ISQLExceptionConverter) Cfg.Environment.ServiceProvider.GetMandatoryService(converterClass); } catch (Exception t) { diff --git a/src/NHibernate/Id/IdentifierGeneratorFactory.cs b/src/NHibernate/Id/IdentifierGeneratorFactory.cs index ebfcd3b58bd..d26ccd1f23e 100644 --- a/src/NHibernate/Id/IdentifierGeneratorFactory.cs +++ b/src/NHibernate/Id/IdentifierGeneratorFactory.cs @@ -219,7 +219,7 @@ public static IIdentifierGenerator Create(string strategy, IType type, IDictiona try { System.Type clazz = GetIdentifierGeneratorClass(strategy, dialect); - var idgen = (IIdentifierGenerator) Cfg.Environment.ObjectsFactory.CreateInstance(clazz); + var idgen = (IIdentifierGenerator) Cfg.Environment.ServiceProvider.GetMandatoryService(clazz); var conf = idgen as IConfigurable; if (conf != null) { diff --git a/src/NHibernate/Impl/SessionFactoryImpl.cs b/src/NHibernate/Impl/SessionFactoryImpl.cs index 3f90f9d0181..0c6f1410fd7 100644 --- a/src/NHibernate/Impl/SessionFactoryImpl.cs +++ b/src/NHibernate/Impl/SessionFactoryImpl.cs @@ -1266,7 +1266,7 @@ private ICurrentSessionContext BuildCurrentSessionContext() switch (impl) { case null: - return null; + break; case "async_local": return new AsyncLocalSessionContext(this); case "call": @@ -1281,8 +1281,8 @@ private ICurrentSessionContext BuildCurrentSessionContext() try { - var implClass = ReflectHelper.ClassForName(impl); - var constructor = implClass.GetConstructor(new [] { typeof(ISessionFactoryImplementor) }); + var implClass = impl != null ? ReflectHelper.ClassForName(impl) : null; + var constructor = implClass?.GetConstructor(new [] { typeof(ISessionFactoryImplementor) }); ICurrentSessionContext context; if (constructor != null) { @@ -1290,7 +1290,9 @@ private ICurrentSessionContext BuildCurrentSessionContext() } else { - context = (ICurrentSessionContext) Environment.ObjectsFactory.CreateInstance(implClass); + context = (ICurrentSessionContext) (implClass != null + ? Environment.ServiceProvider.GetMandatoryService(implClass) + : Environment.ServiceProvider.GetService(typeof(ICurrentSessionContext))); } if (context is ISessionFactoryAwareCurrentSessionContext sessionFactoryAwareContext) { diff --git a/src/NHibernate/Linq/Functions/LinqToHqlGeneratorsRegistryFactory.cs b/src/NHibernate/Linq/Functions/LinqToHqlGeneratorsRegistryFactory.cs index 394ad33dd25..f30960cb2a1 100644 --- a/src/NHibernate/Linq/Functions/LinqToHqlGeneratorsRegistryFactory.cs +++ b/src/NHibernate/Linq/Functions/LinqToHqlGeneratorsRegistryFactory.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using NHibernate.Util; @@ -12,21 +11,12 @@ public sealed class LinqToHqlGeneratorsRegistryFactory public static ILinqToHqlGeneratorsRegistry CreateGeneratorsRegistry(IDictionary properties) { - string registry; - if (properties.TryGetValue(Environment.LinqToHqlGeneratorsRegistry, out registry)) - { - try - { - log.Info("Initializing LinqToHqlGeneratorsRegistry: {0}", registry); - return (ILinqToHqlGeneratorsRegistry) Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(registry)); - } - catch (Exception e) - { - log.Fatal(e, "Could not instantiate LinqToHqlGeneratorsRegistry"); - throw new HibernateException("Could not instantiate LinqToHqlGeneratorsRegistry: " + registry, e); - } - } - return new DefaultLinqToHqlGeneratorsRegistry(); + var instance = PropertiesHelper.GetInstance( + Environment.LinqToHqlGeneratorsRegistry, + properties, + typeof(DefaultLinqToHqlGeneratorsRegistry)); + log.Info("LinqToHqlGeneratorsRegistry: '{0}'", instance.GetType().AssemblyQualifiedName); + return instance; } } } diff --git a/src/NHibernate/Mapping/Collection.cs b/src/NHibernate/Mapping/Collection.cs index de4c97a58f2..e7996afb2c7 100644 --- a/src/NHibernate/Mapping/Collection.cs +++ b/src/NHibernate/Mapping/Collection.cs @@ -152,7 +152,7 @@ public object Comparer { try { - comparer = Cfg.Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(ComparerClassName)); + comparer = Cfg.Environment.ServiceProvider.GetMandatoryService(ReflectHelper.ClassForName(ComparerClassName)); } catch (Exception ex) { diff --git a/src/NHibernate/Properties/PropertyAccessorFactory.cs b/src/NHibernate/Properties/PropertyAccessorFactory.cs index 4a65b5015bf..3bcc891067a 100644 --- a/src/NHibernate/Properties/PropertyAccessorFactory.cs +++ b/src/NHibernate/Properties/PropertyAccessorFactory.cs @@ -260,7 +260,7 @@ private static IPropertyAccessor ResolveCustomAccessor(string accessorName) try { - var result = (IPropertyAccessor) Cfg.Environment.ObjectsFactory.CreateInstance(accessorClass); + var result = (IPropertyAccessor) Cfg.Environment.ServiceProvider.GetMandatoryService(accessorClass); accessors[accessorName] = result; return result; } diff --git a/src/NHibernate/Tool/hbm2ddl/SchemaUpdate.cs b/src/NHibernate/Tool/hbm2ddl/SchemaUpdate.cs index 681a9555f62..7c8ff27eaa9 100644 --- a/src/NHibernate/Tool/hbm2ddl/SchemaUpdate.cs +++ b/src/NHibernate/Tool/hbm2ddl/SchemaUpdate.cs @@ -105,7 +105,7 @@ public static void Main(string[] args) { cfg.SetNamingStrategy( (INamingStrategy) - Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9)))); + Environment.ServiceProvider.GetMandatoryService(ReflectHelper.ClassForName(args[i].Substring(9)))); } } else diff --git a/src/NHibernate/Tool/hbm2ddl/SchemaValidator.cs b/src/NHibernate/Tool/hbm2ddl/SchemaValidator.cs index cfe3d94ff72..1445f15e2bf 100644 --- a/src/NHibernate/Tool/hbm2ddl/SchemaValidator.cs +++ b/src/NHibernate/Tool/hbm2ddl/SchemaValidator.cs @@ -60,7 +60,7 @@ public static void Main(string[] args) { cfg.SetNamingStrategy( (INamingStrategy) - Cfg.Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9)))); + Cfg.Environment.ServiceProvider.GetMandatoryService(ReflectHelper.ClassForName(args[i].Substring(9)))); } } else diff --git a/src/NHibernate/Type/CompositeCustomType.cs b/src/NHibernate/Type/CompositeCustomType.cs index 1588ab4cbd7..51ed7af963a 100644 --- a/src/NHibernate/Type/CompositeCustomType.cs +++ b/src/NHibernate/Type/CompositeCustomType.cs @@ -6,6 +6,7 @@ using NHibernate.Engine; using NHibernate.SqlTypes; using NHibernate.UserTypes; +using NHibernate.Util; using System.Collections.Generic; namespace NHibernate.Type @@ -28,7 +29,7 @@ public CompositeCustomType(System.Type userTypeClass, IDictionary paramet try { - userType = (IUserType) Cfg.Environment.ObjectsFactory.CreateInstance(userTypeClass); + userType = (IUserType) Cfg.Environment.ServiceProvider.GetMandatoryService(userTypeClass); } catch (ArgumentNullException ane) { diff --git a/src/NHibernate/Type/TypeFactory.cs b/src/NHibernate/Type/TypeFactory.cs index cd416deddb6..d1c2819d48b 100644 --- a/src/NHibernate/Type/TypeFactory.cs +++ b/src/NHibernate/Type/TypeFactory.cs @@ -542,7 +542,7 @@ public static IType HeuristicType(string typeName, IDictionary p { try { - type = (IType) Environment.ObjectsFactory.CreateInstance(typeClass); + type = (IType) Environment.ServiceProvider.GetMandatoryService(typeClass); } catch (Exception e) { diff --git a/src/NHibernate/Util/PropertiesHelper.cs b/src/NHibernate/Util/PropertiesHelper.cs index da80f5b0860..e8bb57c2462 100644 --- a/src/NHibernate/Util/PropertiesHelper.cs +++ b/src/NHibernate/Util/PropertiesHelper.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using NHibernate.Bytecode; +using NHibernate.Cfg; namespace NHibernate.Util { @@ -9,10 +11,10 @@ public static class PropertiesHelper { public static bool GetBoolean(string property, IDictionary properties, bool defaultValue) { - string toParse; - properties.TryGetValue(property, out toParse); - bool result; - return bool.TryParse(toParse, out result) ? result : defaultValue; + if (properties == null) + throw new ArgumentNullException(nameof(properties)); + properties.TryGetValue(property, out var toParse); + return bool.TryParse(toParse, out var result) ? result : defaultValue; } public static bool GetBoolean(string property, IDictionary properties) @@ -22,33 +24,34 @@ public static bool GetBoolean(string property, IDictionary prope public static byte? GetByte(string property, IDictionary properties, byte? defaultValue) { - string toParse; - properties.TryGetValue(property, out toParse); - byte result; - return byte.TryParse(toParse, out result) ? result : defaultValue; + if (properties == null) + throw new ArgumentNullException(nameof(properties)); + properties.TryGetValue(property, out var toParse); + return byte.TryParse(toParse, out var result) ? result : defaultValue; } public static int GetInt32(string property, IDictionary properties, int defaultValue) { - string toParse; - properties.TryGetValue(property, out toParse); - int result; - return int.TryParse(toParse, out result) ? result : defaultValue; + if (properties == null) + throw new ArgumentNullException(nameof(properties)); + properties.TryGetValue(property, out var toParse); + return int.TryParse(toParse, out var result) ? result : defaultValue; } public static long GetInt64(string property, IDictionary properties, long defaultValue) { - string toParse; - properties.TryGetValue(property, out toParse); - long result; - return long.TryParse(toParse, out result) ? result : defaultValue; + if (properties == null) + throw new ArgumentNullException(nameof(properties)); + properties.TryGetValue(property, out var toParse); + return long.TryParse(toParse, out var result) ? result : defaultValue; } public static string GetString(string property, IDictionary properties, string defaultValue) { - string value; - properties.TryGetValue(property, out value); - if(value == string.Empty) + if (properties == null) + throw new ArgumentNullException(nameof(properties)); + properties.TryGetValue(property, out var value); + if (value == string.Empty) { value = null; } @@ -57,10 +60,11 @@ public static string GetString(string property, IDictionary prop public static IDictionary ToDictionary(string property, string delim, IDictionary properties) { - IDictionary map = new Dictionary(); + if (properties == null) + throw new ArgumentNullException(nameof(properties)); + var map = new Dictionary(); - string propValue; - if (properties.TryGetValue(property, out propValue)) + if (properties.TryGetValue(property, out var propValue)) { var tokens = new StringTokenizer(propValue, delim, false); using (var en = tokens.GetEnumerator()) @@ -75,5 +79,44 @@ public static IDictionary ToDictionary(string property, string d } return map; } + + /// + /// Get an instance of type by using the . + /// + /// The type to instantiate. + /// The configuration property name. + /// The configuration properties. + /// The default type to instantiate. + /// The instance of the type, or if none is + /// configured and is . + public static TService GetInstance( + string property, IDictionary properties, System.Type defaultType) where TService : class + { + var className = GetString(property, properties, null); + System.Type type = null; + try + { + if (className != null) + { + type = ReflectHelper.ClassForName(className); + return (TService) Cfg.Environment.ServiceProvider.GetMandatoryService(type); + } + + type = typeof(TService); + var instance = (TService) Cfg.Environment.ServiceProvider.GetService(type); + if (instance != null) + { + return instance; + } + + type = defaultType; + return defaultType != null ? (TService) Cfg.Environment.ServiceProvider.GetMandatoryService(defaultType) : null; + } + catch (Exception e) + { + throw new HibernateException( + $"Could not instantiate {typeof(TService).Name}: {type?.AssemblyQualifiedName ?? className}", e); + } + } } } diff --git a/src/NHibernate/Util/ServiceProviderExtensions.cs b/src/NHibernate/Util/ServiceProviderExtensions.cs new file mode 100644 index 00000000000..8d09b2d8eec --- /dev/null +++ b/src/NHibernate/Util/ServiceProviderExtensions.cs @@ -0,0 +1,47 @@ +using System; +using System.Reflection; +using NHibernate.Bytecode; + +namespace NHibernate.Util +{ + internal static class ServiceProviderExtensions + { + /// + /// Get a service, throwing if it cannot be resolved. + /// + /// The service provider. + /// The service interface, base class or concrete implementation class. + /// The service instance. + /// thrown if is . + /// thrown if the service cannot be resolved. + public static object GetMandatoryService(this IServiceProvider serviceProvider, System.Type serviceType) + { + if (serviceType == null) + throw new ArgumentNullException(nameof(serviceType)); + var service = serviceProvider.GetService(serviceType); + if (service != null) + { + return service; + } + + // Some IoC containers require explicit registration for concete types. In order to avoid registering all NHibernate types + // the Activator.CreateInstance is used for them. + Exception innerException = null; + if (serviceType.IsClass && !serviceType.IsAbstract) + { + try + { + return Activator.CreateInstance(serviceType); + } + catch (Exception e) + { + innerException = e; + } + } + + throw new HibernateServiceProviderException( + $"Unable to resolve an instance for {serviceType.AssemblyQualifiedName}, " + + "make sure that the service is registered and a non-null value is returned for it.", innerException); + } + } +} diff --git a/src/NHibernate/nhibernate-configuration.xsd b/src/NHibernate/nhibernate-configuration.xsd index 1ccdfca4e4d..0f8dec65325 100644 --- a/src/NHibernate/nhibernate-configuration.xsd +++ b/src/NHibernate/nhibernate-configuration.xsd @@ -21,11 +21,11 @@ - + - Specify the AssemblyQualifiedName of your custom objects-factory (implementation of IObjectsFactory). - Note: the objects-factory will be effective only when specified in the app.config or web.config. + Specify the AssemblyQualifiedName of your custom service-provider (implementation of IServiceProvider). + Note: the service-provider will be effective only when specified in the app.config or web.config. @@ -349,7 +349,7 @@ - +