Skip to content

Commit d4090f5

Browse files
committed
NH-2931 - Process classes accordingly to inheritance path in mapping by code
1 parent 1c74ebd commit d4090f5

File tree

5 files changed

+120
-7
lines changed

5 files changed

+120
-7
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using NHibernate.Mapping.ByCode;
2+
using NUnit.Framework;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace NHibernate.Test.NHSpecificTest.NH2931
7+
{
8+
[TestFixture]
9+
public class MappingByCodeTest : BugTestCase
10+
{
11+
//no xml mappings here, since we use MappingByCode
12+
protected override System.Collections.IList Mappings
13+
{
14+
get { return new string[0]; }
15+
}
16+
17+
[Test]
18+
public void CompiledMappings_ShouldNotDependOnAddedOrdering_AddedBy_AddMapping()
19+
{
20+
var mapper = new ModelMapper();
21+
mapper.AddMapping<EntityMapping>();
22+
mapper.AddMapping<DerivedClassMapping>();
23+
mapper.AddMapping<BaseClassMapping>();
24+
var config = TestConfigurationHelper.GetDefaultConfiguration();
25+
Assert.DoesNotThrow(() => config.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities()));
26+
}
27+
28+
[Test]
29+
public void CompiledMappings_ShouldNotDependOnAddedOrdering_AddedBy_AddMappings()
30+
{
31+
var mapper = new ModelMapper();
32+
mapper.AddMappings(typeof(EntityMapping).Assembly
33+
.GetExportedTypes()
34+
//only add our test entities/mappings
35+
.Where(t => t.Namespace == typeof(MappingByCodeTest).Namespace));
36+
var config = TestConfigurationHelper.GetDefaultConfiguration();
37+
Assert.DoesNotThrow(() => config.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities()));
38+
}
39+
}
40+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using NHibernate.Mapping.ByCode;
2+
using NHibernate.Mapping.ByCode.Conformist;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH2931
5+
{
6+
public class EntityMapping : ClassMapping<Entity>
7+
{
8+
public EntityMapping()
9+
{
10+
Id(i => i.Id, m => m.Generator(Generators.GuidComb));
11+
}
12+
}
13+
//NOTE: tests may work if the order of mappings is
14+
// 1) BaseClassMapping
15+
// 2) DerivedClassMapping
16+
//but they always fail when
17+
// 1) DerivedClassMapping
18+
// 2) BaseClassMapping
19+
//MappingByCodeTest.CompiledMappings_ShouldNotDependOnAddedOrdering_AddedBy_AddMapping
20+
// explicitly forces the first ordering to occur, but the most common use is simply
21+
// typeof(SomeEntity).Assembly.GetTypes() to register everything; as shown in
22+
//MappingByCodeTest.CompiledMappings_ShouldNotDependOnAddedOrdering_AddedBy_AddMappings
23+
public class DerivedClassMapping : JoinedSubclassMapping<DerivedClass>
24+
{
25+
public DerivedClassMapping()
26+
{
27+
Property(p => p.DerivedProperty);
28+
}
29+
}
30+
public class BaseClassMapping : JoinedSubclassMapping<BaseClass>
31+
{
32+
public BaseClassMapping()
33+
{
34+
Property(p => p.BaseProperty);
35+
}
36+
}
37+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH2931
4+
{
5+
public abstract class Entity
6+
{
7+
public Guid Id { get; private set; }
8+
}
9+
public class BaseClass : Entity
10+
{
11+
public string BaseProperty { get; set; }
12+
}
13+
public class DerivedClass : BaseClass
14+
{
15+
public string DerivedProperty { get; set; }
16+
}
17+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,9 @@
718718
<Compile Include="NHSpecificTest\BagWithLazyExtraAndFilter\Fixture.cs" />
719719
<Compile Include="Linq\ByMethod\DistinctTests.cs" />
720720
<Compile Include="Component\Basic\ComponentWithUniqueConstraintTests.cs" />
721+
<Compile Include="NHSpecificTest\NH2931\Fixture.cs" />
722+
<Compile Include="NHSpecificTest\NH2931\Mappings.cs" />
723+
<Compile Include="NHSpecificTest\NH2931\Models.cs" />
721724
<Compile Include="NHSpecificTest\NH3518\ClassWithXmlMember.cs" />
722725
<Compile Include="NHSpecificTest\NH3518\XmlColumnTest.cs" />
723726
<Compile Include="NHSpecificTest\NH3609\MappingEntity.cs" />

src/NHibernate/Mapping/ByCode/ModelMapper.cs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,10 @@ public HbmMapping CompileMappingFor(IEnumerable<System.Type> types)
548548
{
549549
throw new ArgumentNullException("types");
550550
}
551-
var typeToMap = new HashSet<System.Type>(types);
551+
552+
var typeToMap = types.Distinct()
553+
.OrderBy(x => x, new TypeHierarchyComparer())
554+
.ToList();
552555

553556
string defaultAssemblyName = null;
554557
string defaultNamespace = null;
@@ -563,11 +566,11 @@ public HbmMapping CompileMappingFor(IEnumerable<System.Type> types)
563566
defaultNamespace = firstType.Namespace;
564567
}
565568
var mapping = NewHbmMapping(defaultAssemblyName, defaultNamespace);
566-
foreach (System.Type type in RootClasses(typeToMap))
569+
foreach (var type in RootClasses(typeToMap))
567570
{
568571
MapRootClass(type, mapping);
569572
}
570-
foreach (System.Type type in Subclasses(typeToMap))
573+
foreach (var type in Subclasses(typeToMap))
571574
{
572575
AddSubclassMapping(mapping, type);
573576
}
@@ -580,16 +583,18 @@ public IEnumerable<HbmMapping> CompileMappingForEach(IEnumerable<System.Type> ty
580583
{
581584
throw new ArgumentNullException("types");
582585
}
583-
var typeToMap = new HashSet<System.Type>(types);
586+
var typeToMap = types.Distinct()
587+
.OrderBy(x => x, new TypeHierarchyComparer())
588+
.ToList();
584589

585590
//NH-2831: always use the full name of the assembly because it may come from GAC
586-
foreach (System.Type type in RootClasses(typeToMap))
591+
foreach (var type in RootClasses(typeToMap))
587592
{
588593
var mapping = NewHbmMapping(type.Assembly.GetName().FullName, type.Namespace);
589594
MapRootClass(type, mapping);
590595
yield return mapping;
591596
}
592-
foreach (System.Type type in Subclasses(typeToMap))
597+
foreach (var type in Subclasses(typeToMap))
593598
{
594599
var mapping = NewHbmMapping(type.Assembly.GetName().FullName, type.Namespace);
595600
AddSubclassMapping(mapping, type);
@@ -1815,5 +1820,16 @@ public IEnumerable<HbmMapping> CompileMappingForEachExplicitlyAddedEntity()
18151820
{
18161821
return CompileMappingForEach(customizerHolder.GetAllCustomizedEntities());
18171822
}
1823+
1824+
private class TypeHierarchyComparer : IComparer<System.Type>
1825+
{
1826+
public int Compare(System.Type x, System.Type y)
1827+
{
1828+
if (x == y) return 0;
1829+
if (x.IsAssignableFrom(y)) return -1;
1830+
if (y.IsAssignableFrom(x)) return 1;
1831+
return 0;
1832+
}
1833+
}
18181834
}
1819-
}
1835+
}

0 commit comments

Comments
 (0)