Skip to content

Commit 4e02aa9

Browse files
committed
Add ability to further configure dynamic components templated as a dictionary
1 parent eb76961 commit 4e02aa9

File tree

4 files changed

+76
-54
lines changed

4 files changed

+76
-54
lines changed

src/NHibernate.Test/MappingByCode/ExplicitMappingTests/DynamicComponentMappingTests.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public void WhenMapDynCompoByDictionaryThenMapItAndItsProperties()
5151
map.Component(
5252
x => x.Info,
5353
new Dictionary<string, System.Type>
54-
{ { "MyInt", typeof(int) }, { "MyDate", typeof(DateTime) } },
55-
z => { });
54+
{{"MyInt", typeof(int)}, {"MyDate", typeof(DateTime)}},
55+
z => { z.Property("MyInt", pm => pm.Column("MY_COLUMN")); });
5656
});
5757

5858
var hbmMapping = mapper.CompileMappingFor(new[] { typeof(Person) });
@@ -76,8 +76,8 @@ public void WhenMapDynCompoByDictionaryThenMapItAndItsPropertiesGeneric()
7676
map.Component(
7777
x => x.Info,
7878
new Dictionary<string, System.Type>
79-
{ { "MyInt", typeof(int) }, { "MyDate", typeof(DateTime) } },
80-
z => { });
79+
{{"MyInt", typeof(int)}, {"MyDate", typeof(DateTime)}},
80+
z => { z.Property("MyInt", pm => pm.Column("MY_COLUMN")); });
8181
});
8282

8383
var hbmMapping = mapper.CompileMappingFor(new[] { typeof(PersonWithGenericInfo) });
@@ -101,8 +101,12 @@ public void WhenMapDynCompoByDictionaryThenMapItAndItsPropertiesDynamic()
101101
map.Component(
102102
nameof(PersonWithDynamicInfo.Info),
103103
new Dictionary<string, System.Type>
104-
{ { "MyInt", typeof(int) }, { "MyDate", typeof(DateTime) } },
105-
z => { });
104+
{{"MyInt", typeof(int)}, {"MyDate", typeof(DateTime)}},
105+
z =>
106+
{
107+
z.Property("MyInt", pm => pm.Column("MY_COLUMN"));
108+
z.Component<DateTime>("MyDate");
109+
});
106110
});
107111

108112
var hbmMapping = mapper.CompileMappingFor(new[] { typeof(PersonWithDynamicInfo) });
@@ -126,8 +130,8 @@ public void WhenMapPrivateDynCompoByDictionaryThenMapItAndItsProperties()
126130
map.Component(
127131
"Info",
128132
new Dictionary<string, System.Type>
129-
{ { "MyInt", typeof(int) }, { "MyDate", typeof(DateTime) } },
130-
z => { });
133+
{{"MyInt", typeof(int)}, {"MyDate", typeof(DateTime)}},
134+
z => { z.Property("MyInt", pm => pm.Column("MY_COLUMN")); });
131135
});
132136

133137
var hbmMapping = mapper.CompileMappingFor(new[] { typeof(Person) });
@@ -151,8 +155,8 @@ public void WhenMapPrivateDynCompoByDictionaryThenMapItAndItsPropertiesGeneric()
151155
map.Component(
152156
"Info",
153157
new Dictionary<string, System.Type>
154-
{ { "MyInt", typeof(int) }, { "MyDate", typeof(DateTime) } },
155-
z => { });
158+
{{"MyInt", typeof(int)}, {"MyDate", typeof(DateTime)}},
159+
z => { z.Property("MyInt", pm => pm.Column("MY_COLUMN")); });
156160
});
157161

158162
var hbmMapping = mapper.CompileMappingFor(new[] { typeof(PersonWithGenericInfo) });

src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/ComponentCustomizer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public void Parent<TProperty>(Expression<Func<TComponent, TProperty>> parent) wh
3939

4040
public void Parent(string notVisiblePropertyOrFieldName, Action<IComponentParentMapper> parentMapping)
4141
{
42-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
42+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
4343
AddCustomizer(m => m.Parent(member, parentMapping));
4444
}
4545

src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/DynamicComponentCustomizer.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using System;
2+
using System.Reflection;
23

34
namespace NHibernate.Mapping.ByCode.Impl.CustomizersImpl
45
{
56
public class DynamicComponentCustomizer<TComponent> : PropertyContainerCustomizer<TComponent>,
67
IDynamicComponentMapper<TComponent>
78
{
9+
private readonly System.Type _componentType;
10+
811
public DynamicComponentCustomizer(
912
IModelExplicitDeclarationsHolder explicitDeclarationsHolder,
1013
ICustomizersHolder customizersHolder,
@@ -13,7 +16,7 @@ public DynamicComponentCustomizer(
1316
{
1417
}
1518

16-
public DynamicComponentCustomizer(
19+
internal DynamicComponentCustomizer(
1720
System.Type componentType,
1821
IModelExplicitDeclarationsHolder explicitDeclarationsHolder,
1922
ICustomizersHolder customizersHolder,
@@ -30,7 +33,8 @@ public DynamicComponentCustomizer(
3033
throw new ArgumentNullException(nameof(explicitDeclarationsHolder));
3134
}
3235

33-
explicitDeclarationsHolder.AddAsDynamicComponent(propertyPath.LocalMember, componentType);
36+
_componentType = componentType;
37+
explicitDeclarationsHolder.AddAsDynamicComponent(propertyPath.LocalMember, _componentType);
3438
}
3539

3640
#region IDynamicComponentMapper<TComponent> Members
@@ -66,5 +70,15 @@ public void Unique(bool unique)
6670
}
6771

6872
#endregion
73+
74+
protected override MemberInfo GetRequiredPropertyOrFieldByName(string memberName)
75+
{
76+
var result = _componentType.GetPropertyOrFieldMatchingName(memberName);
77+
if (result == null)
78+
{
79+
throw new MappingException(string.Format("Member not found. The member '{0}' does not exists in type {1}", memberName, _componentType.FullName));
80+
}
81+
return result;
82+
}
6983
}
7084
}

src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/PropertyContainerCustomizer.cs

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ protected virtual void RegisterNoVisiblePropertyMapping(string notVisiblePropert
5555
{
5656
// even seems repetitive, before unify this registration with the registration using Expression take in account that reflection operations
5757
// done unsing expressions are faster than those done with pure reflection.
58-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
58+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
5959
MemberInfo memberOf = member.GetMemberFromReflectedType(typeof(TEntity));
6060
RegistePropertyMapping(mapping, memberOf);
6161
}
@@ -105,9 +105,10 @@ protected void RegisterComponentMapping<TComponent>(Action<IComponentMapper<TCom
105105
/// <typeparam name="TComponent">The type of the template.</typeparam>
106106
public void Component<TComponent>(Expression<Func<TEntity, IDictionary>> property, TComponent dynamicComponentTemplate, Action<IDynamicComponentMapper<TComponent>> mapping)
107107
{
108-
if (dynamicComponentTemplate is IDictionary<string, System.Type> dicTemplate)
108+
if (dynamicComponentTemplate is IEnumerable<KeyValuePair<string, System.Type>> template)
109109
{
110-
RegisterDynamicComponentMapping(property, dicTemplate, mapping);
110+
var componentType = CreateDynamicComponentTypeFromTemplate(template);
111+
RegisterDynamicComponentMapping(property, componentType, mapping);
111112
}
112113
else
113114
{
@@ -126,9 +127,10 @@ public void Component<TComponent>(Expression<Func<TEntity, IDictionary>> propert
126127
/// <typeparam name="TComponent">The type of the template.</typeparam>
127128
public void Component<TComponent>(Expression<Func<TEntity, IDictionary<string, object>>> property, TComponent dynamicComponentTemplate, Action<IDynamicComponentMapper<TComponent>> mapping) where TComponent : class
128129
{
129-
if (dynamicComponentTemplate is IDictionary<string, System.Type> dicTemplate)
130+
if (dynamicComponentTemplate is IEnumerable<KeyValuePair<string, System.Type>> template)
130131
{
131-
RegisterDynamicComponentMapping(property, dicTemplate, mapping);
132+
var componentType = CreateDynamicComponentTypeFromTemplate(template);
133+
RegisterDynamicComponentMapping(property, componentType, mapping);
132134
}
133135
else
134136
{
@@ -142,44 +144,45 @@ protected virtual void RegisterDynamicComponentMapping<TComponent>(Expression<Fu
142144
MemberInfo memberOf = TypeExtensions.DecodeMemberAccessExpressionOf(property);
143145
RegisterDynamicComponentMapping(mapping, member, memberOf);
144146
}
145-
146-
protected virtual void RegisterDynamicComponentMapping<TComponent>(Expression<Func<TEntity, IDictionary<string, object>>> property, Action<IDynamicComponentMapper<TComponent>> mapping) where TComponent : class
147+
148+
protected virtual void RegisterDynamicComponentMapping<TComponent>(Expression<Func<TEntity, IDictionary>> property, System.Type componentType, Action<IDynamicComponentMapper<TComponent>> mapping)
147149
{
148150
MemberInfo member = TypeExtensions.DecodeMemberAccessExpression(property);
149151
MemberInfo memberOf = TypeExtensions.DecodeMemberAccessExpressionOf(property);
150-
RegisterDynamicComponentMapping(mapping, member, memberOf);
152+
RegisterDynamicComponentMapping(componentType, mapping, member, memberOf);
151153
}
152154

153-
protected virtual void RegisterDynamicComponentMapping<TComponent>(
154-
Expression<Func<TEntity, IDictionary>> property,
155-
IDictionary<string, System.Type> template,
156-
Action<IDynamicComponentMapper<TComponent>> mapping)
155+
protected virtual void RegisterDynamicComponentMapping<TComponent>(Expression<Func<TEntity, IDictionary<string, object>>> property, Action<IDynamicComponentMapper<TComponent>> mapping) where TComponent : class
157156
{
158157
MemberInfo member = TypeExtensions.DecodeMemberAccessExpression(property);
159158
MemberInfo memberOf = TypeExtensions.DecodeMemberAccessExpressionOf(property);
160-
RegisterDynamicComponentMapping(template, mapping, member, memberOf);
159+
RegisterDynamicComponentMapping(mapping, member, memberOf);
161160
}
162161

163-
protected virtual void RegisterDynamicComponentMapping<TComponent>(
164-
Expression<Func<TEntity, IDictionary<string, object>>> property,
165-
IDictionary<string, System.Type> template,
166-
Action<IDynamicComponentMapper<TComponent>> mapping)
162+
protected virtual void RegisterDynamicComponentMapping<TComponent>(Expression<Func<TEntity, IDictionary<string, object>>> property, System.Type componentType, Action<IDynamicComponentMapper<TComponent>> mapping)
167163
{
168164
MemberInfo member = TypeExtensions.DecodeMemberAccessExpression(property);
169165
MemberInfo memberOf = TypeExtensions.DecodeMemberAccessExpressionOf(property);
170-
RegisterDynamicComponentMapping(template, mapping, member, memberOf);
166+
RegisterDynamicComponentMapping(componentType, mapping, member, memberOf);
171167
}
172168

173-
protected void RegisterDynamicComponentMapping<TComponent>(IDictionary<string, System.Type> template, Action<IDynamicComponentMapper<TComponent>> mapping, params MemberInfo[] members)
169+
protected void RegisterDynamicComponentMapping<TComponent>(System.Type componentType, Action<IDynamicComponentMapper<TComponent>> mapping, params MemberInfo[] members)
174170
{
175-
var componentType = CreateDynamicComponentTypeFromTemplate(template);
176171
foreach (var member in members)
177172
{
178173
mapping(new DynamicComponentCustomizer<TComponent>(componentType, explicitDeclarationsHolder, CustomizersHolder, new PropertyPath(PropertyPath, member)));
179174
}
180175
}
181176

182-
private static System.Type CreateDynamicComponentTypeFromTemplate(IDictionary<string, System.Type> template)
177+
protected void RegisterDynamicComponentMapping<TComponent>(Action<IDynamicComponentMapper<TComponent>> mapping, params MemberInfo[] members)
178+
{
179+
foreach (var member in members)
180+
{
181+
mapping(new DynamicComponentCustomizer<TComponent>(explicitDeclarationsHolder, CustomizersHolder, new PropertyPath(PropertyPath, member)));
182+
}
183+
}
184+
185+
private static System.Type CreateDynamicComponentTypeFromTemplate(IEnumerable<KeyValuePair<string, System.Type>> template)
183186
{
184187
var assemblyName = new AssemblyName("MyDynamicAssembly");
185188
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
@@ -223,14 +226,6 @@ private static System.Type CreateDynamicComponentTypeFromTemplate(IDictionary<st
223226
return typeBuilder.CreateTypeInfo();
224227
}
225228

226-
protected void RegisterDynamicComponentMapping<TComponent>(Action<IDynamicComponentMapper<TComponent>> mapping, params MemberInfo[] members)
227-
{
228-
foreach (var member in members)
229-
{
230-
mapping(new DynamicComponentCustomizer<TComponent>(explicitDeclarationsHolder, CustomizersHolder, new PropertyPath(PropertyPath, member)));
231-
}
232-
}
233-
234229
public void ManyToOne<TProperty>(Expression<Func<TEntity, TProperty>> property, Action<IManyToOneMapper> mapping)
235230
where TProperty : class
236231
{
@@ -270,7 +265,7 @@ public void OneToOne<TProperty>(Expression<Func<TEntity, TProperty>> property, A
270265

271266
public void OneToOne<TProperty>(string notVisiblePropertyOrFieldName, Action<IOneToOneMapper<TProperty>> mapping) where TProperty : class
272267
{
273-
var member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
268+
var member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
274269
var propertyOrFieldType = member.GetPropertyOrFieldType();
275270
if (typeof(TProperty) != propertyOrFieldType)
276271
{
@@ -467,7 +462,7 @@ protected virtual void RegisterIdBagMapping<TElement>(Action<IIdBagPropertiesMap
467462

468463
public void Set<TElement>(string notVisiblePropertyOrFieldName, Action<ISetPropertiesMapper<TEntity, TElement>> collectionMapping, Action<ICollectionElementRelation<TElement>> mapping)
469464
{
470-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
465+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
471466
AssertCollectionElementType<TElement>(notVisiblePropertyOrFieldName, member);
472467

473468
MemberInfo memberOf = member.GetMemberFromReflectedType(typeof(TEntity));
@@ -497,7 +492,7 @@ public void Set<TElement>(string notVisiblePropertyOrFieldName, Action<ISetPrope
497492

498493
public void Bag<TElement>(string notVisiblePropertyOrFieldName, Action<IBagPropertiesMapper<TEntity, TElement>> collectionMapping, Action<ICollectionElementRelation<TElement>> mapping)
499494
{
500-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
495+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
501496
AssertCollectionElementType<TElement>(notVisiblePropertyOrFieldName, member);
502497

503498
MemberInfo memberOf = member.GetMemberFromReflectedType(typeof(TEntity));
@@ -511,7 +506,7 @@ public void Bag<TElement>(string notVisiblePropertyOrFieldName, Action<IBagPrope
511506

512507
public void List<TElement>(string notVisiblePropertyOrFieldName, Action<IListPropertiesMapper<TEntity, TElement>> collectionMapping, Action<ICollectionElementRelation<TElement>> mapping)
513508
{
514-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
509+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
515510
AssertCollectionElementType<TElement>(notVisiblePropertyOrFieldName, member);
516511

517512
MemberInfo memberOf = member.GetMemberFromReflectedType(typeof(TEntity));
@@ -525,7 +520,7 @@ public void List<TElement>(string notVisiblePropertyOrFieldName, Action<IListPro
525520

526521
public void Map<TKey, TElement>(string notVisiblePropertyOrFieldName, Action<IMapPropertiesMapper<TEntity, TKey, TElement>> collectionMapping, Action<IMapKeyRelation<TKey>> keyMapping, Action<ICollectionElementRelation<TElement>> mapping)
527522
{
528-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
523+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
529524
var propertyOrFieldType = member.GetPropertyOrFieldType();
530525
var keyType = propertyOrFieldType.DetermineDictionaryKeyType();
531526
var collectionElementType = propertyOrFieldType.DetermineDictionaryValueType();
@@ -550,7 +545,7 @@ public void Map<TKey, TElement>(string notVisiblePropertyOrFieldName, Action<IMa
550545

551546
public void IdBag<TElement>(string notVisiblePropertyOrFieldName, Action<IIdBagPropertiesMapper<TEntity, TElement>> collectionMapping, Action<ICollectionElementRelation<TElement>> mapping)
552547
{
553-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
548+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
554549
AssertCollectionElementType<TElement>(notVisiblePropertyOrFieldName, member);
555550

556551
MemberInfo memberOf = member.GetMemberFromReflectedType(typeof(TEntity));
@@ -564,7 +559,7 @@ public void IdBag<TElement>(string notVisiblePropertyOrFieldName, Action<IIdBagP
564559

565560
public void ManyToOne<TProperty>(string notVisiblePropertyOrFieldName, Action<IManyToOneMapper> mapping) where TProperty : class
566561
{
567-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
562+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
568563
var propertyOrFieldType = member.GetPropertyOrFieldType();
569564
if (!typeof(TProperty).Equals(propertyOrFieldType))
570565
{
@@ -577,7 +572,7 @@ public void ManyToOne<TProperty>(string notVisiblePropertyOrFieldName, Action<IM
577572

578573
public void Component<TComponent>(string notVisiblePropertyOrFieldName, Action<IComponentMapper<TComponent>> mapping)
579574
{
580-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
575+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
581576
var propertyOrFieldType = member.GetPropertyOrFieldType();
582577
if (!typeof(TComponent).Equals(propertyOrFieldType))
583578
{
@@ -605,12 +600,13 @@ public void Component<TComponent>(string notVisiblePropertyOrFieldName)
605600
/// <typeparam name="TComponent">The type of the template.</typeparam>
606601
public void Component<TComponent>(string notVisiblePropertyOrFieldName, TComponent dynamicComponentTemplate, Action<IDynamicComponentMapper<TComponent>> mapping)
607602
{
608-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
603+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
609604
MemberInfo memberOf = member.GetMemberFromReflectedType(typeof(TEntity));
610605

611-
if (dynamicComponentTemplate is IDictionary<string, System.Type> dicTemplate)
606+
if (dynamicComponentTemplate is IEnumerable<KeyValuePair<string, System.Type>> template)
612607
{
613-
RegisterDynamicComponentMapping(dicTemplate, mapping, member, memberOf);
608+
var componentType = CreateDynamicComponentTypeFromTemplate(template);
609+
RegisterDynamicComponentMapping(componentType, mapping, member, memberOf);
614610
}
615611
else
616612
{
@@ -620,7 +616,7 @@ public void Component<TComponent>(string notVisiblePropertyOrFieldName, TCompone
620616

621617
public void Any<TProperty>(string notVisiblePropertyOrFieldName, System.Type idTypeOfMetaType, Action<IAnyMapper> mapping) where TProperty : class
622618
{
623-
MemberInfo member = GetPropertyOrFieldMatchingNameOrThrow(notVisiblePropertyOrFieldName);
619+
MemberInfo member = GetRequiredPropertyOrFieldByName(notVisiblePropertyOrFieldName);
624620
var propertyOrFieldType = member.GetPropertyOrFieldType();
625621
if (!typeof(TProperty).Equals(propertyOrFieldType))
626622
{
@@ -631,6 +627,14 @@ public void Any<TProperty>(string notVisiblePropertyOrFieldName, System.Type idT
631627
RegisterAnyMapping<TProperty>(mapping, idTypeOfMetaType, member, memberOf);
632628
}
633629

630+
protected virtual MemberInfo GetRequiredPropertyOrFieldByName(string memberName)
631+
{
632+
#pragma warning disable 618
633+
return GetPropertyOrFieldMatchingNameOrThrow(memberName);
634+
#pragma warning restore 618
635+
}
636+
637+
[Obsolete("Please use GetRequiredPropertyOrFieldByName instead.")]
634638
public static MemberInfo GetPropertyOrFieldMatchingNameOrThrow(string memberName)
635639
{
636640
var result = typeof(TEntity).GetPropertyOrFieldMatchingName(memberName);

0 commit comments

Comments
 (0)