Skip to content

Commit ea32bc5

Browse files
committed
If some properties of an ICompositeUserType wrongly returns null, throw a helpful exception instead of just NRE. Code adapted from Rory Plaire. NH-2297
1 parent 109724f commit ea32bc5

File tree

8 files changed

+208
-0
lines changed

8 files changed

+208
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH2297
4+
{
5+
public class CustomCompositeUserType
6+
{
7+
public virtual String Value1 { get; set; }
8+
public virtual String Value2 { get; set; }
9+
}
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Collections;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH2297
4+
{
5+
public class EntityNH2297
6+
{
7+
public virtual int Id { get; set; }
8+
9+
public virtual CustomCompositeUserType CustomTypeValue { get; set; }
10+
}
11+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using System.Collections;
3+
using System.Reflection;
4+
using NHibernate.Cfg;
5+
using NUnit.Framework;
6+
7+
namespace NHibernate.Test.NHSpecificTest.NH2297
8+
{
9+
[TestFixture]
10+
public class Fixture // Purposefully doesn't inherit from BugTestCase
11+
{
12+
[TestCase(".MappingsNames.hbm.xml",
13+
ExpectedException = typeof (InvalidOperationException),
14+
ExpectedMessage =
15+
"ICompositeUserType NHibernate.Test.NHSpecificTest.NH2297.InvalidNamesCustomCompositeUserType returned a null value for 'PropertyNames'."
16+
)]
17+
[TestCase(".MappingsTypes.hbm.xml",
18+
ExpectedException = typeof (InvalidOperationException),
19+
ExpectedMessage =
20+
"ICompositeUserType NHibernate.Test.NHSpecificTest.NH2297.InvalidTypesCustomCompositeUserType returned a null value for 'PropertyTypes'."
21+
)]
22+
public void InvalidCustomCompositeUserTypeThrowsMeaningfulException(string mappingFile)
23+
{
24+
var cfg = new Configuration();
25+
26+
if (TestConfigurationHelper.hibernateConfigFile != null)
27+
cfg.Configure(TestConfigurationHelper.hibernateConfigFile);
28+
29+
const string MappingsAssembly = "NHibernate.Test";
30+
31+
Assembly assembly = Assembly.Load(MappingsAssembly);
32+
33+
string ns = GetType().Namespace;
34+
string bugNumber = ns.Substring(ns.LastIndexOf('.') + 1);
35+
36+
cfg.AddResource(MappingsAssembly + "." + "NHSpecificTest." + bugNumber + mappingFile, assembly);
37+
38+
// build session factory creates the invalid custom type mapper, and throws the exception
39+
cfg.BuildSessionFactory();
40+
}
41+
}
42+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using System;
2+
using System.Data;
3+
using NHibernate.Engine;
4+
using NHibernate.Type;
5+
using NHibernate.UserTypes;
6+
7+
namespace NHibernate.Test.NHSpecificTest.NH2297
8+
{
9+
public class InvalidNamesCustomCompositeUserType : InvalidCustomCompositeUserTypeBase
10+
{
11+
public override string[] PropertyNames
12+
{
13+
// This is an invalid return value
14+
get { return null; }
15+
}
16+
}
17+
18+
19+
public class InvalidTypesCustomCompositeUserType : InvalidCustomCompositeUserTypeBase
20+
{
21+
public override Type.IType[] PropertyTypes
22+
{
23+
// This is an invalid return value
24+
get { return null; }
25+
}
26+
}
27+
28+
29+
/// <summary>
30+
/// An invalid custom user type mapper.
31+
/// </summary>
32+
[Serializable]
33+
public abstract class InvalidCustomCompositeUserTypeBase : ICompositeUserType
34+
{
35+
public System.Type ReturnedClass
36+
{
37+
get { return typeof (CustomCompositeUserType); }
38+
}
39+
40+
public bool IsMutable
41+
{
42+
get { return true; }
43+
}
44+
45+
public virtual String[] PropertyNames
46+
{
47+
get { return new[] {"Value1", "Value2"}; }
48+
}
49+
50+
public virtual Type.IType[] PropertyTypes
51+
{
52+
get { return new IType[] {NHibernateUtil.String, NHibernateUtil.String}; }
53+
}
54+
55+
public object Assemble(object cached, ISessionImplementor session, object owner)
56+
{
57+
return DeepCopy(cached);
58+
}
59+
60+
public object Disassemble(Object value, ISessionImplementor session)
61+
{
62+
return DeepCopy(value);
63+
}
64+
65+
public Object DeepCopy(Object a)
66+
{
67+
return a;
68+
}
69+
70+
public new bool Equals(object x, object y)
71+
{
72+
return (x == y) || (x != null && y != null && (x.Equals(y)));
73+
}
74+
75+
public object NullSafeGet(System.Data.IDataReader rs, String[] names, NHibernate.Engine.ISessionImplementor session,
76+
Object owner)
77+
{
78+
return NHibernateUtil.String.NullSafeGet(rs, names[0], session, owner);
79+
}
80+
81+
public void NullSafeSet(System.Data.IDbCommand st, Object value, int index,
82+
bool[] settable, NHibernate.Engine.ISessionImplementor session)
83+
{
84+
throw new NotImplementedException();
85+
}
86+
87+
public Object GetPropertyValue(Object component, int property)
88+
{
89+
return null;
90+
}
91+
92+
public void SetPropertyValue(Object object1, int i, Object object2)
93+
{
94+
95+
}
96+
97+
public int GetHashCode(object x)
98+
{
99+
return x == null ? typeof (string).GetHashCode() : x.GetHashCode();
100+
}
101+
102+
public object Replace(object original, object target, ISessionImplementor session, object owner)
103+
{
104+
return DeepCopy(original);
105+
}
106+
}
107+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
namespace="NHibernate.Test.NHSpecificTest.NH2297"
4+
assembly="NHibernate.Test">
5+
6+
<class name="EntityNH2297" schema="test">
7+
<id name="Id">
8+
<generator class="increment"/>
9+
</id>
10+
<property name="CustomTypeValue" type="NHibernate.Test.NHSpecificTest.NH2297.InvalidNamesCustomCompositeUserType, NHibernate.Test"/>
11+
</class>
12+
13+
</hibernate-mapping>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
namespace="NHibernate.Test.NHSpecificTest.NH2297"
4+
assembly="NHibernate.Test">
5+
6+
<class name="EntityNH2297" schema="test">
7+
<id name="Id">
8+
<generator class="increment"/>
9+
</id>
10+
<property name="CustomTypeValue" type="NHibernate.Test.NHSpecificTest.NH2297.InvalidTypesCustomCompositeUserType, NHibernate.Test"/>
11+
</class>
12+
13+
</hibernate-mapping>

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,10 @@
666666
<Compile Include="NHSpecificTest\BagWithLazyExtraAndFilter\Domain.cs" />
667667
<Compile Include="NHSpecificTest\BagWithLazyExtraAndFilter\Fixture.cs" />
668668
<Compile Include="Component\Basic\ComponentWithUniqueConstraintTests.cs" />
669+
<Compile Include="NHSpecificTest\NH2297\CustomCompositeUserType.cs" />
670+
<Compile Include="NHSpecificTest\NH2297\Entity.cs" />
671+
<Compile Include="NHSpecificTest\NH2297\Fixture.cs" />
672+
<Compile Include="NHSpecificTest\NH2297\InvalidCustomCompositeUserTypeBase.cs" />
669673
<Compile Include="NHSpecificTest\NH3374\Document.cs" />
670674
<Compile Include="NHSpecificTest\NH3374\FixtureByCode.cs" />
671675
<Compile Include="NHSpecificTest\NH2042\Model.cs" />
@@ -2867,6 +2871,8 @@
28672871
<EmbeddedResource Include="NHSpecificTest\NH1291AnonExample\Mappings.hbm.xml" />
28682872
</ItemGroup>
28692873
<ItemGroup>
2874+
<EmbeddedResource Include="NHSpecificTest\NH2297\MappingsNames.hbm.xml" />
2875+
<EmbeddedResource Include="NHSpecificTest\NH2297\MappingsTypes.hbm.xml" />
28702876
<EmbeddedResource Include="NHSpecificTest\NH2042\Mappings.hbm.xml" />
28712877
<EmbeddedResource Include="NHSpecificTest\NH2860\Mappings.hbm.xml" />
28722878
<EmbeddedResource Include="NHSpecificTest\NH3332\Mappings.hbm.xml" />

src/NHibernate/Type/CompositeCustomType.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ public CompositeCustomType(System.Type userTypeClass, IDictionary<string, string
5353
{
5454
LoggerProvider.LoggerFor(typeof(CustomType)).WarnFormat("the custom composite class '{0}' handled by '{1}' is not Serializable: ", userType.ReturnedClass, userTypeClass);
5555
}
56+
57+
// This is to be nice to an application developer.
58+
if (userType.PropertyTypes == null)
59+
throw new InvalidOperationException(String.Format("ICompositeUserType {0} returned a null value for 'PropertyTypes'.", userType.GetType()));
60+
if (userType.PropertyNames == null)
61+
throw new InvalidOperationException(String.Format("ICompositeUserType {0} returned a null value for 'PropertyNames'.", userType.GetType()));
5662
}
5763

5864
public virtual IType[] Subtypes

0 commit comments

Comments
 (0)