Skip to content

Commit 1997661

Browse files
maca88fredericDelaporte
authored andcommitted
Decouple configuration of IObjectsFactory from BytecodeProvider (#1758)
Fixes #1671
1 parent e1565b4 commit 1997661

37 files changed

+362
-98
lines changed

doc/reference/modules/configuration.xml

Lines changed: 89 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -441,14 +441,6 @@ var session = sessions.OpenSession(conn);
441441
at runtime. All are optional and have reasonable default values.
442442
</para>
443443

444-
<para>
445-
Some properties are system-level properties. They can only be set manually by setting static properties of
446-
<literal>NHibernate.Cfg.Environment</literal> class or be defined in the
447-
<literal>&lt;hibernate-configuration&gt;</literal> section of the application
448-
configuration file. These properties cannot be set using <literal>Configuration.SetProperties</literal> or
449-
the <literal>hibernate.cfg.xml</literal> configuration file.
450-
</para>
451-
452444
<table frame="topbot" id="configuration-optional-properties" revision="3">
453445
<title>NHibernate Configuration Properties</title>
454446
<tgroup cols="2">
@@ -514,53 +506,6 @@ var session = sessions.OpenSession(conn);
514506
</para>
515507
</entry>
516508
</row>
517-
<row>
518-
<entry>
519-
<literal>use_reflection_optimizer</literal>
520-
</entry>
521-
<entry>
522-
Enables use of a runtime-generated class to set or get properties of an entity
523-
or component instead of using runtime reflection. This is a system-level property.
524-
The use of the reflection optimizer inflicts a certain startup cost on the
525-
application but should lead to better performance in the long run.
526-
Defaults to <literal>true</literal>.
527-
<para>
528-
You can not set this property in <literal>hibernate.cfg.xml</literal>, but only
529-
in <literal>&lt;hibernate-configuration&gt;</literal> section of the application
530-
configuration file or by code by setting
531-
<literal>NHibernate.Cfg.Environment.UseReflectionOptimizer</literal>
532-
before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
533-
</para>
534-
<para>
535-
<emphasis role="strong">eg.</emphasis>
536-
<literal>true</literal> | <literal>false</literal>
537-
</para>
538-
</entry>
539-
</row>
540-
<row>
541-
<entry>
542-
<literal>bytecode.provider</literal>
543-
</entry>
544-
<entry>
545-
Specifies the bytecode provider to use to optimize the use of reflection in NHibernate.
546-
This is a system-level property.
547-
Use <literal>null</literal> to disable the optimization completely, <literal>lcg</literal>
548-
to use built-in lightweight code generation, or the class name of a custom
549-
<literal>IBytecodeProvider</literal> implementation. Defaults to <literal>lcg</literal>.
550-
<para>
551-
You can not set this property in <literal>hibernate.cfg.xml</literal>, but only
552-
in <literal>&lt;hibernate-configuration&gt;</literal> section of the application
553-
configuration file or by code by setting
554-
<literal>NHibernate.Cfg.Environment.BytecodeProvider</literal>
555-
before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
556-
</para>
557-
<para>
558-
<emphasis role="strong">eg.</emphasis>
559-
<literal>null</literal> | <literal>lcg</literal> |
560-
<literal>classname.of.BytecodeProvider, assembly</literal>
561-
</para>
562-
</entry>
563-
</row>
564509
<row>
565510
<entry>
566511
<literal>cache.use_second_level_cache</literal>
@@ -1467,6 +1412,95 @@ in the parameter binding.</programlisting>
14671412

14681413
</sect2>
14691414

1415+
<sect2 id="configuration-optional-systemlevel">
1416+
<title>System level optional properties</title>
1417+
1418+
<para>
1419+
Some properties are system-level properties. They can only be set manually by setting static
1420+
properties of <literal>NHibernate.Cfg.Environment</literal> class or be defined in the
1421+
<literal>&lt;hibernate-configuration&gt;</literal> section of the application configuration
1422+
file, as direct sub-elements. These properties can neither be set using
1423+
<literal>Configuration.SetProperties</literal> or the <literal>hibernate.cfg.xml</literal>
1424+
configuration file, nor be set as <literal>&lt;session-factory&gt;</literal> properties.
1425+
</para>
1426+
1427+
<table frame="topbot" id="configuration-systemlevel-properties">
1428+
<title>NHibernate system level properties</title>
1429+
<tgroup cols="2">
1430+
<colspec colname="c1" colwidth="1*"/>
1431+
<colspec colname="c2" colwidth="1*"/>
1432+
<thead>
1433+
<row>
1434+
<entry>Property name</entry>
1435+
<entry>Purpose</entry>
1436+
</row>
1437+
</thead>
1438+
<tbody>
1439+
<row>
1440+
<entry>
1441+
<literal>bytecode-provider</literal>
1442+
</entry>
1443+
<entry>
1444+
<para>
1445+
Specifies the bytecode provider to use to optimize the use of reflection in NHibernate.
1446+
Use <literal>null</literal> to disable the optimization completely, <literal>lcg</literal>
1447+
to use built-in lightweight code generation, or the assembly qualified class name of a custom
1448+
<literal>IBytecodeProvider</literal> implementation. Defaults to <literal>lcg</literal>.
1449+
</para>
1450+
<programlisting><![CDATA[<bytecode-provider
1451+
type="lcg|null|className" />]]></programlisting>
1452+
<para>
1453+
You can also set this property by code by setting
1454+
<literal>NHibernate.Cfg.Environment.BytecodeProvider</literal>
1455+
before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
1456+
</para>
1457+
</entry>
1458+
</row>
1459+
<row>
1460+
<entry>
1461+
<literal>objects-factory</literal>
1462+
</entry>
1463+
<entry>
1464+
<para>
1465+
Specifies a custom objects factory to use for instantiating NHibernate dependencies.
1466+
Use the assembly qualified class name of a custom <literal>IObjectsFactory</literal>
1467+
implementation.
1468+
</para>
1469+
<programlisting><![CDATA[<bytecode-provider
1470+
type="className" />]]></programlisting>
1471+
<para>
1472+
You can also set this property by code by setting
1473+
<literal>NHibernate.Cfg.Environment.ObjectsFactory</literal>
1474+
before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
1475+
</para>
1476+
</entry>
1477+
</row>
1478+
<row>
1479+
<entry>
1480+
<literal>reflection-optimizer</literal>
1481+
</entry>
1482+
<entry>
1483+
<para>
1484+
Enables use of a runtime-generated class to set or get properties of an entity
1485+
or component instead of using runtime reflection. The use of the reflection
1486+
optimizer inflicts a certain startup cost on the application but should lead to
1487+
better performance in the long run. Defaults to <literal>true</literal>.
1488+
</para>
1489+
<programlisting><![CDATA[<reflection-optimizer
1490+
use="true|false"/>]]></programlisting>
1491+
<para>
1492+
You can also set this property by code by setting
1493+
<literal>NHibernate.Cfg.Environment.UseReflectionOptimizer</literal>
1494+
before creating any <literal>NHibernate.Cfg.Configuration</literal> instance.
1495+
</para>
1496+
</entry>
1497+
</row>
1498+
</tbody>
1499+
</tgroup>
1500+
</table>
1501+
1502+
</sect2>
1503+
14701504
</sect1>
14711505

14721506
<sect1 id="configuration-logging">

src/NHibernate.Test/CfgTest/ConfigurationSchemaFixture.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,30 @@ public void IgnoreSystemOutOfAppConfig()
5757
Assert.AreEqual(hc.UseReflectionOptimizer, newhc.UseReflectionOptimizer);
5858
}
5959

60+
[Test]
61+
public void ObjectsFactory()
62+
{
63+
Assume.That(TestsContext.ExecutingWithVsTest, Is.False);
64+
65+
var xml =
66+
@"<?xml version='1.0' encoding='utf-8' ?>
67+
<hibernate-configuration xmlns='urn:nhibernate-configuration-2.2'>
68+
<objects-factory type='test'/>
69+
<session-factory>
70+
</session-factory>
71+
</hibernate-configuration>";
72+
73+
HibernateConfiguration hc;
74+
using (var xtr = new XmlTextReader(xml, XmlNodeType.Document, null))
75+
{
76+
hc = new HibernateConfiguration(xtr);
77+
Assert.That(hc.ObjectsFactoryType, Is.Null);
78+
}
79+
80+
hc = HibernateConfiguration.FromAppConfig(xml);
81+
Assert.That(hc.ObjectsFactoryType, Is.EqualTo("test"));
82+
}
83+
6084
[Test]
6185
public void EmptyFactoryNotAllowed()
6286
{
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using NHibernate.Bytecode;
4+
using NUnit.Framework;
5+
using Environment = NHibernate.Cfg.Environment;
6+
7+
namespace NHibernate.Test.CfgTest
8+
{
9+
[TestFixture]
10+
public class CustomObjectsFactoryTest
11+
{
12+
private class MyObjectsFactory : IObjectsFactory
13+
{
14+
public object CreateInstance(System.Type type)
15+
{
16+
throw new NotImplementedException();
17+
}
18+
19+
public object CreateInstance(System.Type type, bool nonPublic)
20+
{
21+
throw new NotImplementedException();
22+
}
23+
24+
public object CreateInstance(System.Type type, params object[] ctorArgs)
25+
{
26+
throw new NotImplementedException();
27+
}
28+
}
29+
private class InvalidObjectsFactory
30+
{
31+
}
32+
private class InvalidNoCtorObjectsFactory : MyObjectsFactory
33+
{
34+
public InvalidNoCtorObjectsFactory(string pizza) {}
35+
}
36+
37+
[Test]
38+
public void WhenNoShortCutUsedThenCanBuildObjectsFactory()
39+
{
40+
var properties = new Dictionary<string, string> { { Environment.PropertyBytecodeProvider, typeof(MyObjectsFactory).AssemblyQualifiedName } };
41+
Assert.That(() => Environment.BuildObjectsFactory(properties), Throws.Nothing);
42+
}
43+
44+
[Test]
45+
public void WhenNoShortCutUsedThenCanBuildInstanceOfConfiguredObjectsFactory()
46+
{
47+
var properties = new Dictionary<string, string> { { Environment.PropertyObjectsFactory, typeof(MyObjectsFactory).AssemblyQualifiedName } };
48+
Assert.That(Environment.BuildObjectsFactory(properties), Is.InstanceOf<MyObjectsFactory>());
49+
}
50+
51+
[Test]
52+
public void WhenInvalidThenThrow()
53+
{
54+
var properties = new Dictionary<string, string> { { Environment.PropertyObjectsFactory, typeof(InvalidObjectsFactory).AssemblyQualifiedName } };
55+
Assert.That(() => Environment.BuildObjectsFactory(properties), Throws.TypeOf<HibernateObjectsFactoryException>());
56+
}
57+
58+
[Test]
59+
public void WhenNoDefaultCtorThenThrow()
60+
{
61+
var properties = new Dictionary<string, string> { { Environment.PropertyObjectsFactory, typeof(InvalidNoCtorObjectsFactory).AssemblyQualifiedName } };
62+
Assert.That(() => Environment.BuildObjectsFactory(properties), Throws.TypeOf<HibernateObjectsFactoryException>()
63+
.And.InnerException.Message.Contains("constructor was not found"));
64+
}
65+
}
66+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public partial class DriverForSubstitutedCommand : IDriver
132132

133133
public DriverForSubstitutedCommand()
134134
{
135-
_driverImplementation = (IDriver) Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(DriverClass);
135+
_driverImplementation = (IDriver) Cfg.Environment.ObjectsFactory.CreateInstance(DriverClass);
136136
}
137137

138138
DbCommand IDriver.GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes)

src/NHibernate.Test/TypesTest/AbstractDateTimeTypeFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ public class ClientDriverWithParamsStats : IDriver
533533

534534
public ClientDriverWithParamsStats()
535535
{
536-
_driverImplementation = (IDriver) Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(DriverClass);
536+
_driverImplementation = (IDriver) Cfg.Environment.ObjectsFactory.CreateInstance(DriverClass);
537537
}
538538

539539
private static void Inc<T>(T type, IDictionary<T, int> dic)

src/NHibernate/Async/Tool/hbm2ddl/SchemaExport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ private async Task ExecuteInitializedAsync(Action<string> scriptAction, bool exe
187187
cancellationToken.ThrowIfCancellationRequested();
188188
if (dialect.SupportsSqlBatches)
189189
{
190-
var objFactory = Environment.BytecodeProvider.ObjectsFactory;
190+
var objFactory = Environment.ObjectsFactory;
191191
ScriptSplitter splitter = (ScriptSplitter)objFactory.CreateInstance(typeof(ScriptSplitter), sql);
192192

193193
foreach (string stmt in splitter)

src/NHibernate/Async/Tool/hbm2ddl/SchemaUpdate.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public partial class SchemaUpdate
7878
{
7979
cfg.SetNamingStrategy(
8080
(INamingStrategy)
81-
Environment.BytecodeProvider.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9))));
81+
Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9))));
8282
}
8383
}
8484
else

src/NHibernate/Async/Tool/hbm2ddl/SchemaValidator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public partial class SchemaValidator
4848
{
4949
cfg.SetNamingStrategy(
5050
(INamingStrategy)
51-
Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9))));
51+
Cfg.Environment.ObjectsFactory.CreateInstance(ReflectHelper.ClassForName(args[i].Substring(9))));
5252
}
5353
}
5454
else

src/NHibernate/Bytecode/AbstractBytecodeProvider.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ namespace NHibernate.Bytecode
66
{
77
public abstract class AbstractBytecodeProvider : IBytecodeProvider, IInjectableProxyFactoryFactory, IInjectableCollectionTypeFactoryClass
88
{
9-
private readonly IObjectsFactory objectsFactory = new ActivatorObjectsFactory();
109
protected System.Type proxyFactoryFactory;
1110
private ICollectionTypeFactory collectionTypeFactory;
1211
private System.Type collectionTypeFactoryClass = typeof(Type.DefaultCollectionTypeFactory);
@@ -21,7 +20,7 @@ public virtual IProxyFactoryFactory ProxyFactoryFactory
2120
{
2221
try
2322
{
24-
return (IProxyFactoryFactory) ObjectsFactory.CreateInstance(proxyFactoryFactory);
23+
return (IProxyFactoryFactory) Cfg.Environment.ObjectsFactory.CreateInstance(proxyFactoryFactory);
2524
}
2625
catch (Exception e)
2726
{
@@ -35,10 +34,9 @@ public virtual IProxyFactoryFactory ProxyFactoryFactory
3534

3635
public abstract IReflectionOptimizer GetReflectionOptimizer(System.Type clazz, IGetter[] getters, ISetter[] setters);
3736

38-
public virtual IObjectsFactory ObjectsFactory
39-
{
40-
get { return objectsFactory; }
41-
}
37+
// Since 5.2
38+
[Obsolete("Please use NHibernate.Cfg.Environment.ObjectsFactory instead")]
39+
public virtual IObjectsFactory ObjectsFactory => Cfg.Environment.ObjectsFactory;
4240

4341
public virtual ICollectionTypeFactory CollectionTypeFactory
4442
{
@@ -49,7 +47,7 @@ public virtual ICollectionTypeFactory CollectionTypeFactory
4947
try
5048
{
5149
collectionTypeFactory =
52-
(ICollectionTypeFactory) ObjectsFactory.CreateInstance(collectionTypeFactoryClass);
50+
(ICollectionTypeFactory) Cfg.Environment.ObjectsFactory.CreateInstance(collectionTypeFactoryClass);
5351
}
5452
catch (Exception e)
5553
{
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Runtime.Serialization;
3+
4+
namespace NHibernate.Bytecode
5+
{
6+
/// <summary>
7+
/// Thrown if NHibernate can't instantiate the <see cref="IObjectsFactory"/> type.
8+
/// </summary>
9+
[Serializable]
10+
public class HibernateObjectsFactoryException : HibernateException
11+
{
12+
public HibernateObjectsFactoryException() {}
13+
public HibernateObjectsFactoryException(string message) : base(message) {}
14+
public HibernateObjectsFactoryException(string message, Exception inner) : base(message, inner) {}
15+
16+
protected HibernateObjectsFactoryException(SerializationInfo info, StreamingContext context) : base(info, context) {}
17+
}
18+
}

0 commit comments

Comments
 (0)