Permalink
Browse files

Decouple configuration of IObjectsFactory from BytecodeProvider (#1758)

Fixes #1671
  • Loading branch information...
maca88 authored and fredericDelaporte committed Jun 23, 2018
1 parent e1565b4 commit 1997661f43893ccb0b93dd0309c1db0a8c3c9588
Showing with 362 additions and 98 deletions.
  1. +89 −55 doc/reference/modules/configuration.xml
  2. +24 −0 src/NHibernate.Test/CfgTest/ConfigurationSchemaFixture.cs
  3. +66 −0 src/NHibernate.Test/CfgTest/CustomObjectsFactoryTest.cs
  4. +1 −1 src/NHibernate.Test/NHSpecificTest/GH1547/Fixture.cs
  5. +1 −1 src/NHibernate.Test/TypesTest/AbstractDateTimeTypeFixture.cs
  6. +1 −1 src/NHibernate/Async/Tool/hbm2ddl/SchemaExport.cs
  7. +1 −1 src/NHibernate/Async/Tool/hbm2ddl/SchemaUpdate.cs
  8. +1 −1 src/NHibernate/Async/Tool/hbm2ddl/SchemaValidator.cs
  9. +5 −7 src/NHibernate/Bytecode/AbstractBytecodeProvider.cs
  10. +18 −0 src/NHibernate/Bytecode/HibernateObjectsFactoryException.cs
  11. +3 −0 src/NHibernate/Bytecode/IBytecodeProvider.cs
  12. +1 −1 src/NHibernate/Cfg/Configuration.cs
  13. +3 −0 src/NHibernate/Cfg/ConfigurationSchema/CfgXmlHelper.cs
  14. +25 −0 src/NHibernate/Cfg/ConfigurationSchema/HibernateConfiguration.cs
  15. +82 −3 src/NHibernate/Cfg/Environment.cs
  16. +6 −6 src/NHibernate/Cfg/SettingsFactory.cs
  17. +1 −1 src/NHibernate/Cfg/XmlHbmBinding/AuxiliaryDatabaseObjectFactory.cs
  18. +1 −1 src/NHibernate/Connection/ConnectionProvider.cs
  19. +1 −1 src/NHibernate/Connection/ConnectionProviderFactory.cs
  20. +1 −1 src/NHibernate/Dialect/Dialect.cs
  21. +2 −2 src/NHibernate/Driver/ReflectionDriveConnectionCommandProvider.cs
  22. +1 −1 src/NHibernate/Exceptions/SQLExceptionConverterFactory.cs
  23. +1 −1 src/NHibernate/Id/IdentifierGeneratorFactory.cs
  24. +1 −1 src/NHibernate/Impl/SessionFactoryImpl.cs
  25. +1 −1 src/NHibernate/Linq/Functions/LinqToHqlGeneratorsRegistryFactory.cs
  26. +1 −1 src/NHibernate/Mapping/Collection.cs
  27. +1 −1 src/NHibernate/Properties/PropertyAccessorFactory.cs
  28. +1 −1 src/NHibernate/Tool/hbm2ddl/SchemaExport.cs
  29. +1 −1 src/NHibernate/Tool/hbm2ddl/SchemaUpdate.cs
  30. +1 −1 src/NHibernate/Tool/hbm2ddl/SchemaValidator.cs
  31. +1 −1 src/NHibernate/Transform/AliasToBeanResultTransformer.cs
  32. +1 −1 src/NHibernate/Tuple/PocoInstantiator.cs
  33. +1 −1 src/NHibernate/Type/CompositeCustomType.cs
  34. +1 −1 src/NHibernate/Type/CustomCollectionType.cs
  35. +1 −1 src/NHibernate/Type/CustomType.cs
  36. +1 −1 src/NHibernate/Type/TypeFactory.cs
  37. +14 −0 src/NHibernate/nhibernate-configuration.xsd
@@ -441,14 +441,6 @@ var session = sessions.OpenSession(conn);
at runtime. All are optional and have reasonable default values.
</para>
- <para>
- Some properties are system-level properties. They can only be set manually by setting static properties of
- <literal>NHibernate.Cfg.Environment</literal> class or be defined in the
- <literal>&lt;hibernate-configuration&gt;</literal> section of the application
- configuration file. These properties cannot be set using <literal>Configuration.SetProperties</literal> or
- the <literal>hibernate.cfg.xml</literal> configuration file.
- </para>
-
<table frame="topbot" id="configuration-optional-properties" revision="3">
<title>NHibernate Configuration Properties</title>
<tgroup cols="2">
@@ -514,53 +506,6 @@ var session = sessions.OpenSession(conn);
</para>
</entry>
</row>
- <row>
- <entry>
- <literal>use_reflection_optimizer</literal>
- </entry>
- <entry>
- Enables use of a runtime-generated class to set or get properties of an entity
- or component instead of using runtime reflection. This is a system-level property.
- The use of the reflection optimizer inflicts a certain startup cost on the
- application but should lead to better performance in the long run.
- Defaults to <literal>true</literal>.
- <para>
- You can not set this property in <literal>hibernate.cfg.xml</literal>, but only
- in <literal>&lt;hibernate-configuration&gt;</literal> section of the application
- configuration file or by code by setting
- <literal>NHibernate.Cfg.Environment.UseReflectionOptimizer</literal>
- before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
- </para>
- <para>
- <emphasis role="strong">eg.</emphasis>
- <literal>true</literal> | <literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>bytecode.provider</literal>
- </entry>
- <entry>
- Specifies the bytecode provider to use to optimize the use of reflection in NHibernate.
- This is a system-level property.
- Use <literal>null</literal> to disable the optimization completely, <literal>lcg</literal>
- to use built-in lightweight code generation, or the class name of a custom
- <literal>IBytecodeProvider</literal> implementation. Defaults to <literal>lcg</literal>.
- <para>
- You can not set this property in <literal>hibernate.cfg.xml</literal>, but only
- in <literal>&lt;hibernate-configuration&gt;</literal> section of the application
- configuration file or by code by setting
- <literal>NHibernate.Cfg.Environment.BytecodeProvider</literal>
- before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
- </para>
- <para>
- <emphasis role="strong">eg.</emphasis>
- <literal>null</literal> | <literal>lcg</literal> |
- <literal>classname.of.BytecodeProvider, assembly</literal>
- </para>
- </entry>
- </row>
<row>
<entry>
<literal>cache.use_second_level_cache</literal>
@@ -1467,6 +1412,95 @@ in the parameter binding.</programlisting>
</sect2>
+ <sect2 id="configuration-optional-systemlevel">
+ <title>System level optional properties</title>
+
+ <para>
+ Some properties are system-level properties. They can only be set manually by setting static
+ properties of <literal>NHibernate.Cfg.Environment</literal> class or be defined in the
+ <literal>&lt;hibernate-configuration&gt;</literal> section of the application configuration
+ file, as direct sub-elements. These properties can neither be set using
+ <literal>Configuration.SetProperties</literal> or the <literal>hibernate.cfg.xml</literal>
+ configuration file, nor be set as <literal>&lt;session-factory&gt;</literal> properties.
+ </para>
+
+ <table frame="topbot" id="configuration-systemlevel-properties">
+ <title>NHibernate system level properties</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Property name</entry>
+ <entry>Purpose</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>bytecode-provider</literal>
+ </entry>
+ <entry>
+ <para>
+ Specifies the bytecode provider to use to optimize the use of reflection in NHibernate.
+ Use <literal>null</literal> to disable the optimization completely, <literal>lcg</literal>
+ to use built-in lightweight code generation, or the assembly qualified class name of a custom
+ <literal>IBytecodeProvider</literal> implementation. Defaults to <literal>lcg</literal>.
+ </para>
+ <programlisting><![CDATA[<bytecode-provider
+ type="lcg|null|className" />]]></programlisting>
+ <para>
+ You can also set this property by code by setting
+ <literal>NHibernate.Cfg.Environment.BytecodeProvider</literal>
+ before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>objects-factory</literal>
+ </entry>
+ <entry>
+ <para>
+ Specifies a custom objects factory to use for instantiating NHibernate dependencies.
+ Use the assembly qualified class name of a custom <literal>IObjectsFactory</literal>
+ implementation.
+ </para>
+ <programlisting><![CDATA[<bytecode-provider
+ type="className" />]]></programlisting>
+ <para>
+ You can also set this property by code by setting
+ <literal>NHibernate.Cfg.Environment.ObjectsFactory</literal>
+ before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>reflection-optimizer</literal>
+ </entry>
+ <entry>
+ <para>
+ Enables use of a runtime-generated class to set or get properties of an entity
+ or component instead of using runtime reflection. The use of the reflection
+ optimizer inflicts a certain startup cost on the application but should lead to
+ better performance in the long run. Defaults to <literal>true</literal>.
+ </para>
+ <programlisting><![CDATA[<reflection-optimizer
+ use="true|false"/>]]></programlisting>
+ <para>
+ You can also set this property by code by setting
+ <literal>NHibernate.Cfg.Environment.UseReflectionOptimizer</literal>
+ before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </sect2>
+
</sect1>
<sect1 id="configuration-logging">
@@ -57,6 +57,30 @@ public void IgnoreSystemOutOfAppConfig()
Assert.AreEqual(hc.UseReflectionOptimizer, newhc.UseReflectionOptimizer);
}
+ [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'>
+ <objects-factory type='test'/>
+ <session-factory>
+ </session-factory>
+</hibernate-configuration>";
+
+ HibernateConfiguration hc;
+ using (var xtr = new XmlTextReader(xml, XmlNodeType.Document, null))
+ {
+ hc = new HibernateConfiguration(xtr);
+ Assert.That(hc.ObjectsFactoryType, Is.Null);
+ }
+
+ hc = HibernateConfiguration.FromAppConfig(xml);
+ Assert.That(hc.ObjectsFactoryType, Is.EqualTo("test"));
+ }
+
[Test]
public void EmptyFactoryNotAllowed()
{
@@ -0,0 +1,66 @@
+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<string, string> { { Environment.PropertyBytecodeProvider, typeof(MyObjectsFactory).AssemblyQualifiedName } };
+ Assert.That(() => Environment.BuildObjectsFactory(properties), Throws.Nothing);
+ }
+
+ [Test]
+ public void WhenNoShortCutUsedThenCanBuildInstanceOfConfiguredObjectsFactory()
+ {
+ var properties = new Dictionary<string, string> { { Environment.PropertyObjectsFactory, typeof(MyObjectsFactory).AssemblyQualifiedName } };
+ Assert.That(Environment.BuildObjectsFactory(properties), Is.InstanceOf<MyObjectsFactory>());
+ }
+
+ [Test]
+ public void WhenInvalidThenThrow()
+ {
+ var properties = new Dictionary<string, string> { { Environment.PropertyObjectsFactory, typeof(InvalidObjectsFactory).AssemblyQualifiedName } };
+ Assert.That(() => Environment.BuildObjectsFactory(properties), Throws.TypeOf<HibernateObjectsFactoryException>());
+ }
+
+ [Test]
+ public void WhenNoDefaultCtorThenThrow()
+ {
+ var properties = new Dictionary<string, string> { { Environment.PropertyObjectsFactory, typeof(InvalidNoCtorObjectsFactory).AssemblyQualifiedName } };
+ Assert.That(() => Environment.BuildObjectsFactory(properties), Throws.TypeOf<HibernateObjectsFactoryException>()
+ .And.InnerException.Message.Contains("constructor was not found"));
+ }
+ }
+}
@@ -132,7 +132,7 @@ public partial class DriverForSubstitutedCommand : IDriver
public DriverForSubstitutedCommand()
{
- _driverImplementation = (IDriver) Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(DriverClass);
+ _driverImplementation = (IDriver) Cfg.Environment.ObjectsFactory.CreateInstance(DriverClass);
}
DbCommand IDriver.GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes)
@@ -533,7 +533,7 @@ public class ClientDriverWithParamsStats : IDriver
public ClientDriverWithParamsStats()
{
- _driverImplementation = (IDriver) Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(DriverClass);
+ _driverImplementation = (IDriver) Cfg.Environment.ObjectsFactory.CreateInstance(DriverClass);
}
private static void Inc<T>(T type, IDictionary<T, int> dic)
@@ -187,7 +187,7 @@ public Task DropAsync(TextWriter exportOutput, bool execute, CancellationToken c
cancellationToken.ThrowIfCancellationRequested();
if (dialect.SupportsSqlBatches)
{
- var objFactory = Environment.BytecodeProvider.ObjectsFactory;
+ var objFactory = Environment.ObjectsFactory;
ScriptSplitter splitter = (ScriptSplitter)objFactory.CreateInstance(typeof(ScriptSplitter), sql);
foreach (string stmt in splitter)
@@ -78,7 +78,7 @@ public partial class SchemaUpdate
{
cfg.SetNamingStrategy(
(INamingStrategy)
- Environment.BytecodeProvider.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9))));
+ Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9))));
}
}
else
@@ -48,7 +48,7 @@ public partial class SchemaValidator
{
cfg.SetNamingStrategy(
(INamingStrategy)
- Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9))));
+ Cfg.Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9))));
}
}
else
@@ -6,7 +6,6 @@ namespace NHibernate.Bytecode
{
public abstract class AbstractBytecodeProvider : IBytecodeProvider, IInjectableProxyFactoryFactory, IInjectableCollectionTypeFactoryClass
{
- private readonly IObjectsFactory objectsFactory = new ActivatorObjectsFactory();
protected System.Type proxyFactoryFactory;
private ICollectionTypeFactory collectionTypeFactory;
private System.Type collectionTypeFactoryClass = typeof(Type.DefaultCollectionTypeFactory);
@@ -21,7 +20,7 @@ public virtual IProxyFactoryFactory ProxyFactoryFactory
{
try
{
- return (IProxyFactoryFactory) ObjectsFactory.CreateInstance(proxyFactoryFactory);
+ return (IProxyFactoryFactory) Cfg.Environment.ObjectsFactory.CreateInstance(proxyFactoryFactory);
}
catch (Exception e)
{
@@ -35,10 +34,9 @@ public virtual IProxyFactoryFactory ProxyFactoryFactory
public abstract IReflectionOptimizer GetReflectionOptimizer(System.Type clazz, IGetter[] getters, ISetter[] setters);
- public virtual IObjectsFactory ObjectsFactory
- {
- get { return objectsFactory; }
- }
+ // Since 5.2
+ [Obsolete("Please use NHibernate.Cfg.Environment.ObjectsFactory instead")]
+ public virtual IObjectsFactory ObjectsFactory => Cfg.Environment.ObjectsFactory;
public virtual ICollectionTypeFactory CollectionTypeFactory
{
@@ -49,7 +47,7 @@ public virtual ICollectionTypeFactory CollectionTypeFactory
try
{
collectionTypeFactory =
- (ICollectionTypeFactory) ObjectsFactory.CreateInstance(collectionTypeFactoryClass);
+ (ICollectionTypeFactory) Cfg.Environment.ObjectsFactory.CreateInstance(collectionTypeFactoryClass);
}
catch (Exception e)
{
@@ -0,0 +1,18 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace NHibernate.Bytecode
+{
+ /// <summary>
+ /// Thrown if NHibernate can't instantiate the <see cref="IObjectsFactory"/> type.
+ /// </summary>
+ [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) {}
+ }
+}
@@ -1,3 +1,4 @@
+using System;
using NHibernate.Properties;
namespace NHibernate.Bytecode
@@ -26,6 +27,8 @@ public interface IBytecodeProvider
/// <remarks>
/// For entities <see cref="IReflectionOptimizer"/> and its implementations.
/// </remarks>
+ // Since 5.2
+ [Obsolete("Please use NHibernate.Cfg.Environment.ObjectsFactory instead")]
IObjectsFactory ObjectsFactory { get; }
/// <summary>
@@ -1902,7 +1902,7 @@ public void SetListeners(ListenerType type, string[] listenerClasses)
{
try
{
- listeners[i] = Environment.BytecodeProvider.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(listenerClasses[i]));
+ listeners[i] = Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(listenerClasses[i]));
}
catch (Exception e)
{
Oops, something went wrong.

0 comments on commit 1997661

Please sign in to comment.