Skip to content

Decouple configuration of IObjectsFactory from BytecodeProvider #1758

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 6 commits into from
Jun 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 89 additions & 55 deletions doc/reference/modules/configuration.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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">
Expand Down
24 changes: 24 additions & 0 deletions src/NHibernate.Test/CfgTest/ConfigurationSchemaFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
66 changes: 66 additions & 0 deletions src/NHibernate.Test/CfgTest/CustomObjectsFactoryTest.cs
Original file line number Diff line number Diff line change
@@ -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"));
}
}
}
2 changes: 1 addition & 1 deletion src/NHibernate.Test/NHSpecificTest/GH1547/Fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Async/Tool/hbm2ddl/SchemaExport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ private async Task ExecuteInitializedAsync(Action<string> scriptAction, bool exe
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)
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Async/Tool/hbm2ddl/SchemaUpdate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Async/Tool/hbm2ddl/SchemaValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 5 additions & 7 deletions src/NHibernate/Bytecode/AbstractBytecodeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -21,7 +20,7 @@ public virtual IProxyFactoryFactory ProxyFactoryFactory
{
try
{
return (IProxyFactoryFactory) ObjectsFactory.CreateInstance(proxyFactoryFactory);
return (IProxyFactoryFactory) Cfg.Environment.ObjectsFactory.CreateInstance(proxyFactoryFactory);
}
catch (Exception e)
{
Expand All @@ -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
{
Expand All @@ -49,7 +47,7 @@ public virtual ICollectionTypeFactory CollectionTypeFactory
try
{
collectionTypeFactory =
(ICollectionTypeFactory) ObjectsFactory.CreateInstance(collectionTypeFactoryClass);
(ICollectionTypeFactory) Cfg.Environment.ObjectsFactory.CreateInstance(collectionTypeFactoryClass);
}
catch (Exception e)
{
Expand Down
18 changes: 18 additions & 0 deletions src/NHibernate/Bytecode/HibernateObjectsFactoryException.cs
Original file line number Diff line number Diff line change
@@ -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) {}
}
}
3 changes: 3 additions & 0 deletions src/NHibernate/Bytecode/IBytecodeProvider.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using NHibernate.Properties;

namespace NHibernate.Bytecode
Expand Down Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Cfg/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Loading