Skip to content

Add in ByCode support of all type mappings on Id #1848

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
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
84 changes: 84 additions & 0 deletions src/NHibernate.Test/MappingByCode/MappersTests/IdMapperTest.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System;
using System.Linq;
using System.Reflection;
using NHibernate.Mapping.ByCode;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode.Impl;
using NHibernate.Type;
using NUnit.Framework;

namespace NHibernate.Test.MappingByCode.MappersTests
Expand Down Expand Up @@ -80,6 +82,11 @@ private class Related
public int Id { get; set; }
}

private enum MyEnum
{
One
}

[Test]
public void CanSetGeneratorForeign()
{
Expand Down Expand Up @@ -210,5 +217,82 @@ public void CanSqlType()
mapper.Column(x => x.SqlType("CHAR(10)"));
Assert.That(hbmId.column[0].sqltype, Is.EqualTo("CHAR(10)"));
}

[Test]
public void WhenSetTypeByITypeThenSetTypeName()
{
var hbmId = new HbmId();
var mapper = new IdMapper(null, hbmId);
mapper.Type(NHibernateUtil.String);

Assert.That(hbmId.Type.name, Is.EqualTo("String"));
}

[Test]
public void WhenSetTypeByIUserTypeThenSetTypeName()
{
var hbmId = new HbmId();
var mapper = new IdMapper(null, hbmId);
mapper.Type<MyType>();

Assert.That(hbmId.Type.name, Does.Contain("MyType"));
Assert.That(hbmId.type, Is.Null);
}

[Test]
public void WhenSetTypeByICompositeUserTypeThenSetTypeName()
{
var hbmId = new HbmId();
var mapper = new IdMapper(null, hbmId);
mapper.Type<MyCompoType>();

Assert.That(hbmId.Type.name, Does.Contain("MyCompoType"));
Assert.That(hbmId.type, Is.Null);
}

[Test]
public void WhenSetTypeByIUserTypeWithParamsThenSetType()
{
var hbmId = new HbmId();
var mapper = new IdMapper(null, hbmId);
mapper.Type<MyType>(new { Param1 = "a", Param2 = 12 });

Assert.That(hbmId.type1, Is.Null);
Assert.That(hbmId.Type.name, Does.Contain("MyType"));
Assert.That(hbmId.Type.param, Has.Length.EqualTo(2));
Assert.That(hbmId.Type.param.Select(p => p.name), Is.EquivalentTo(new [] {"Param1", "Param2"}));
Assert.That(hbmId.Type.param.Select(p => p.GetText()), Is.EquivalentTo(new [] {"a", "12"}));
}

[Test]
public void WhenSetTypeByIUserTypeWithNullParamsThenSetTypeName()
{
var hbmId = new HbmId();
var mapper = new IdMapper(null, hbmId);
mapper.Type<MyType>(null);

Assert.That(hbmId.Type.name, Does.Contain("MyType"));
Assert.That(hbmId.type, Is.Null);
}

[Test]
public void WhenSetTypeByITypeTypeThenSetType()
{
var hbmId = new HbmId();
var mapper = new IdMapper(null, hbmId);
mapper.Type<EnumStringType<MyEnum>>();

Assert.That(hbmId.Type.name, Does.Contain(typeof(EnumStringType<MyEnum>).FullName));
Assert.That(hbmId.type, Is.Null);
}

[Test]
public void WhenSetInvalidTypeThenThrow()
{
var hbmId = new HbmId();
var mapper = new IdMapper(null, hbmId);
Assert.That(() => mapper.Type(typeof(object), null), Throws.TypeOf<ArgumentOutOfRangeException>());
Assert.That(() => mapper.Type(null, null), Throws.TypeOf<ArgumentNullException>());
}
}
}
33 changes: 27 additions & 6 deletions src/NHibernate/Mapping/ByCode/IIdMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using NHibernate.Mapping.ByCode.Impl;
using NHibernate.Type;
using NHibernate.Util;

namespace NHibernate.Mapping.ByCode
{
Expand All @@ -9,12 +11,31 @@ public interface IIdMapper : IAccessorPropertyMapper, IColumnsMapper
void Generator(IGeneratorDef generator, Action<IGeneratorMapper> generatorMapping);

void Type(IIdentifierType persistentType);
//void Type<TPersistentType>() where TPersistentType : IIdentifierType;
//void Type<TPersistentType>(object parameters) where TPersistentType : IIdentifierType;
//void Type(System.System.Type persistentType, object parameters);
//void Column(Action<IColumnMapper> columnMapper);
//void Columns(params Action<IColumnMapper>[] columnMapper);
Copy link
Member Author

@fredericDelaporte fredericDelaporte Sep 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The column methods are not lacking, they are here through inherited IColumnsMapper.

void UnsavedValue(object value);
void Length(int length);
}
}

public static class IdMapperExtensions
{
public static void Type<TPersistentType>(this IIdMapper idMapper)
{
Type<TPersistentType>(idMapper, null);
}

public static void Type<TPersistentType>(this IIdMapper idMapper, object parameters)
{
Type(idMapper, typeof (TPersistentType), parameters);
}

// 6.0 TODO: move into IIdMapper,
// and probably add an ITypeMapper for mutualizing it with IElementMapper and IPropertyMapper
// (Note that there is no IKeyPropertyMapper to be concerned with, the KeyPropertyMapper use IPropertyMapper
// directly instead.)
public static void Type(this IIdMapper idMapper, System.Type persistentType, object parameters)
{
ReflectHelper
.CastOrThrow<IdMapper>(idMapper, "Type method with a type argument")
.Type(persistentType, parameters);
}
}
}
35 changes: 34 additions & 1 deletion src/NHibernate/Mapping/ByCode/Impl/IdMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Reflection;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Type;
using NHibernate.UserTypes;

namespace NHibernate.Mapping.ByCode.Impl
{
Expand Down Expand Up @@ -66,6 +67,38 @@ public void Type(IIdentifierType persistentType)
}
}

public void Type(System.Type persistentType, object parameters)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a(!) future I would like to have a method which accepts IDictionary<string, object> for parameters.

{
if (persistentType == null)
{
throw new ArgumentNullException(nameof(persistentType));
}
if (!typeof (IUserType).IsAssignableFrom(persistentType) && !typeof (IType).IsAssignableFrom(persistentType) && !typeof (ICompositeUserType).IsAssignableFrom(persistentType))
{
throw new ArgumentOutOfRangeException(nameof(persistentType), "Expected type implementing IUserType, ICompositeUserType or IType.");
}
if (parameters != null)
{
hbmId.type1 = null;
var hbmType = new HbmType
{
name = persistentType.AssemblyQualifiedName,
param = (from pi in parameters.GetType().GetProperties()
let pname = pi.Name
let pvalue = pi.GetValue(parameters, null)
select
new HbmParam {name = pname, Text = new[] {ReferenceEquals(pvalue, null) ? "null" : pvalue.ToString()}})
.ToArray()
};
hbmId.type = hbmType;
}
else
{
hbmId.type1 = persistentType.AssemblyQualifiedName;
hbmId.type = null;
}
}

public void UnsavedValue(object value)
{
hbmId.unsavedvalue = value != null ? value.ToString() : "null";
Expand Down Expand Up @@ -182,4 +215,4 @@ public void Access(System.Type accessorType) {}

#endregion
}
}
}