Skip to content

Commit 977e409

Browse files
NH-3884 - Allow redefining the NHibernate default type for a .Net type.
1 parent c7814a1 commit 977e409

File tree

5 files changed

+133
-12
lines changed

5 files changed

+133
-12
lines changed
Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<Import Project="../../build-common/NHibernate.props" />
3-
43
<PropertyGroup>
54
<Description>The Unit Tests for NHibernate.</Description>
6-
75
<TargetFramework>net461</TargetFramework>
86
<NoWarn>$(NoWarn);3001;3002;3003;3005</NoWarn>
97
</PropertyGroup>
10-
118
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
129
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
1310
<TreatSpecificWarningsAsErrors />
1411
</PropertyGroup>
15-
1612
<ItemGroup>
1713
<None Remove="**\*.hbm.xml" />
1814
<None Remove="**\*.jpg" />
1915
<None Update="DbScripts\*.sql">
2016
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
2117
</None>
2218
</ItemGroup>
23-
2419
<ItemGroup>
2520
<EmbeddedResource Include="**\*.hbm.xml" Exclude="bin\**\*.*" />
2621
<EmbeddedResource Include="**\*.jpg" />
@@ -32,13 +27,11 @@
3227
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
3328
</EmbeddedResource>
3429
</ItemGroup>
35-
3630
<ItemGroup>
3731
<Content Include="..\NHibernate.DomainModel\ABC.hbm.xml" Link="ABC.hbm.xml">
3832
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
3933
</Content>
4034
</ItemGroup>
41-
4235
<ItemGroup>
4336
<PackageReference Include="Antlr3.Runtime" Version="3.5.1" />
4437
<PackageReference Include="Iesi.Collections" Version="4.0.2" />
@@ -51,20 +44,16 @@
5144
<PackageReference Include="NUnit3TestAdapter" Version="3.8.0" />
5245
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
5346
</ItemGroup>
54-
5547
<ItemGroup>
5648
<ProjectReference Include="..\NHibernate.DomainModel\NHibernate.DomainModel.csproj" />
5749
<ProjectReference Include="..\NHibernate\NHibernate.csproj" />
5850
</ItemGroup>
59-
6051
<ItemGroup>
6152
<Reference Include="System.Configuration" />
6253
<Reference Include="System.Data.OracleClient" />
6354
<Reference Include="System.Transactions" />
6455
</ItemGroup>
65-
6656
<ItemGroup>
6757
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
6858
</ItemGroup>
69-
70-
</Project>
59+
</Project>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace NHibernate.Test.TypesTest
4+
{
5+
public class ChangeDefaultTypeClass
6+
{
7+
public int Id { get; set; }
8+
9+
public DateTime NormalDateTimeValue { get; set; } = DateTime.Today;
10+
}
11+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
3+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
4+
5+
<class
6+
name="NHibernate.Test.TypesTest.ChangeDefaultTypeClass, NHibernate.Test"
7+
table="bc_datetime"
8+
>
9+
10+
<id name="Id" column="id">
11+
<generator class="assigned"/>
12+
</id>
13+
14+
<property name="NormalDateTimeValue"/>
15+
</class>
16+
</hibernate-mapping>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
using NHibernate.Cfg;
5+
using NHibernate.Engine;
6+
using NHibernate.Impl;
7+
using NHibernate.Type;
8+
using NUnit.Framework;
9+
10+
namespace NHibernate.Test.TypesTest
11+
{
12+
/// <summary>
13+
/// TestFixtures for changing a default .Net type.
14+
/// </summary>
15+
[TestFixture]
16+
public class ChangeDefaultTypeFixture : TypeFixtureBase
17+
{
18+
protected override string TypeName => "ChangeDefaultType";
19+
20+
private IType _originalDefaultDateTimeType;
21+
private IType _testDefaultDateTimeType;
22+
23+
protected override void Configure(Configuration configuration)
24+
{
25+
_originalDefaultDateTimeType = TypeFactory.GetDefaultTypeFor(typeof(DateTime));
26+
Assert.That(_originalDefaultDateTimeType, Is.Not.Null);
27+
_testDefaultDateTimeType = NHibernateUtil.DateTime.Equals(_originalDefaultDateTimeType)
28+
? (IType) NHibernateUtil.Timestamp
29+
: NHibernateUtil.DateTime;
30+
TypeFactory.SetDefaultType<DateTime>(_testDefaultDateTimeType);
31+
base.Configure(configuration);
32+
}
33+
34+
protected override void DropSchema()
35+
{
36+
base.DropSchema();
37+
if (_originalDefaultDateTimeType != null)
38+
TypeFactory.SetDefaultType<DateTime>(_originalDefaultDateTimeType);
39+
}
40+
41+
[Test]
42+
public void DefaultType()
43+
{
44+
Assert.That(TypeFactory.GetDefaultTypeFor(typeof(DateTime)), Is.EqualTo(_testDefaultDateTimeType));
45+
}
46+
47+
[Test]
48+
public void PropertyType()
49+
{
50+
Assert.That(
51+
Sfi.GetClassMetadata(typeof(ChangeDefaultTypeClass))
52+
.GetPropertyType(nameof(ChangeDefaultTypeClass.NormalDateTimeValue)),
53+
Is.EqualTo(_testDefaultDateTimeType));
54+
}
55+
56+
[Test]
57+
public void GuessType()
58+
{
59+
Assert.That(NHibernateUtil.GuessType(typeof(DateTime)), Is.EqualTo(_testDefaultDateTimeType));
60+
}
61+
62+
[Test]
63+
public void ParameterType()
64+
{
65+
var namedParametersField = typeof(AbstractQueryImpl)
66+
.GetField("namedParameters", BindingFlags.Instance | BindingFlags.NonPublic);
67+
Assert.That(namedParametersField, Is.Not.Null, "Missing internal field");
68+
69+
using (var s = OpenSession())
70+
{
71+
// Query where the parameter type cannot be deducted from compared entity property
72+
var q = s.CreateQuery($"from {nameof(ChangeDefaultTypeClass)} where :date1 = :date2 or :date1 = :date3")
73+
.SetParameter("date1", DateTime.Now)
74+
.SetDateTime("date2", DateTime.Now)
75+
.SetTimestamp("date3", DateTime.Now);
76+
77+
var namedParameters = namedParametersField.GetValue(q) as Dictionary<string, TypedValue>;
78+
Assert.That(namedParameters, Is.Not.Null, "Unable to retrieve parameters internal field");
79+
Assert.That(namedParameters["date1"].Type, Is.EqualTo(_testDefaultDateTimeType));
80+
Assert.That(namedParameters["date2"].Type, Is.EqualTo(NHibernateUtil.DateTime));
81+
Assert.That(namedParameters["date3"].Type, Is.EqualTo(NHibernateUtil.Timestamp));
82+
}
83+
}
84+
}
85+
}

src/NHibernate/Type/TypeFactory.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Xml;
77
using System.Xml.Linq;
88
using NHibernate.Bytecode;
9+
using NHibernate.Cfg;
910
using NHibernate.Classic;
1011
using NHibernate.SqlTypes;
1112
using NHibernate.UserTypes;
@@ -279,6 +280,25 @@ private static void RegisterBuiltInTypes()
279280
len => new SerializableType(typeof (object), SqlTypeFactory.GetBinary(len))));
280281
}
281282

283+
/// <summary>
284+
/// <para>Defines which NHibernate type should be chosen by default for handling a given .Net type.</para>
285+
/// <para>This must be done before any operation on NHibernate, including building its
286+
/// <see cref="Configuration" /> and building session factory. Otherwise the behavior will be undefined.</para>
287+
/// </summary>
288+
/// <param name="targetType">The NHibernate type.</param>
289+
/// <typeparam name="T">The .Net type.</typeparam>
290+
public static void SetDefaultType<T>(IType targetType)
291+
{
292+
if (targetType == null)
293+
throw new ArgumentNullException(nameof(targetType));
294+
295+
var type = typeof(T);
296+
foreach (var alias in GetClrTypeAliases(type))
297+
{
298+
typeByTypeOfName[alias] = targetType;
299+
}
300+
}
301+
282302
private static ICollectionTypeFactory CollectionTypeFactory =>
283303
Environment.BytecodeProvider.CollectionTypeFactory;
284304

0 commit comments

Comments
 (0)