Skip to content

Commit 41fe85e

Browse files
committed
Adds an overload for AddValueObjectConverters with ComplexPropertyBuilder
1 parent 671a994 commit 41fe85e

File tree

5 files changed

+94
-17
lines changed

5 files changed

+94
-17
lines changed

src/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Sources/Extensions/EntityTypeBuilderExtensions.cs

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,60 @@ public static OwnedNavigationBuilder AddValueObjectConverters(
129129
return entityTypeBuilder;
130130
}
131131

132+
#if COMPLEX_TYPES
133+
134+
/// <summary>
135+
/// Adds value converter to all properties that are Smart Enums or keyed Value Objects.
136+
/// Properties with a value provider are skipped.
137+
/// </summary>
138+
/// <param name="complexPropertyBuilder">The complex property builder.</param>
139+
/// <param name="validateOnWrite">In case of a validatable Smart Enum, ensures that the item is valid before writing it to database.</param>
140+
/// <param name="useConstructorForRead">For keyed value objects only. Use the constructor instead of the factory method when reading the data from database.</param>
141+
/// <param name="configureEnumsAndKeyedValueObjects">Action for further configuration of the property.</param>
142+
/// <returns>The entity type builder for method chaining.</returns>
143+
public static ComplexPropertyBuilder<TComplex> AddValueObjectConverters<TComplex>(
144+
this ComplexPropertyBuilder<TComplex> complexPropertyBuilder,
145+
bool validateOnWrite,
146+
bool useConstructorForRead = true,
147+
Action<IMutableProperty>? configureEnumsAndKeyedValueObjects = null)
148+
where TComplex : class
149+
{
150+
((ComplexPropertyBuilder)complexPropertyBuilder).AddValueObjectConverters(
151+
validateOnWrite,
152+
useConstructorForRead,
153+
configureEnumsAndKeyedValueObjects);
154+
155+
return complexPropertyBuilder;
156+
}
157+
158+
/// <summary>
159+
/// Adds value converter to all properties that are Smart Enums or keyed Value Objects.
160+
/// Properties with a value provider are skipped.
161+
/// </summary>
162+
/// <param name="complexPropertyBuilder">The complex property builder.</param>
163+
/// <param name="validateOnWrite">In case of a validatable Smart Enum, ensures that the item is valid before writing it to database.</param>
164+
/// <param name="useConstructorForRead">For keyed value objects only. Use the constructor instead of the factory method when reading the data from database.</param>
165+
/// <param name="configureEnumsAndKeyedValueObjects">Action for further configuration of the property.</param>
166+
/// <returns>The entity type builder for method chaining.</returns>
167+
public static ComplexPropertyBuilder AddValueObjectConverters(
168+
this ComplexPropertyBuilder complexPropertyBuilder,
169+
bool validateOnWrite,
170+
bool useConstructorForRead = true,
171+
Action<IMutableProperty>? configureEnumsAndKeyedValueObjects = null)
172+
{
173+
configureEnumsAndKeyedValueObjects ??= Empty.Action;
174+
175+
AddConvertersForComplexProperty(
176+
complexPropertyBuilder.Metadata,
177+
validateOnWrite,
178+
useConstructorForRead,
179+
null, // Cache for a single entity will be more of a drawback
180+
configureEnumsAndKeyedValueObjects);
181+
182+
return complexPropertyBuilder;
183+
}
184+
#endif
185+
132186
internal static void AddConvertersToEntity(
133187
this IMutableEntityType entity,
134188
bool validateOnWrite,
@@ -330,13 +384,23 @@ private static void AddConverterForComplexProperties(
330384
{
331385
foreach (var complexProperty in entity.GetComplexProperties())
332386
{
333-
AddSmartEnumAndKeyedValueObjects(complexProperty.ComplexType, validateOnWrite, useConstructorForRead, converterLookup, configureEnumsAndKeyedValueObjects);
334-
AddNonKeyedValueObjectMembers(complexProperty.ComplexType);
335-
336-
AddConverterForScalarProperties(complexProperty.ComplexType, validateOnWrite, useConstructorForRead, converterLookup, configureEnumsAndKeyedValueObjects);
337-
AddConverterForComplexProperties(complexProperty.ComplexType, validateOnWrite, useConstructorForRead, converterLookup, configureEnumsAndKeyedValueObjects);
387+
AddConvertersForComplexProperty(complexProperty, validateOnWrite, useConstructorForRead, converterLookup, configureEnumsAndKeyedValueObjects);
338388
}
339389
}
390+
391+
private static void AddConvertersForComplexProperty(
392+
IMutableComplexProperty complexProperty,
393+
bool validateOnWrite,
394+
bool useConstructorForRead,
395+
Dictionary<Type, ValueConverter>? converterLookup,
396+
Action<IMutableProperty> configureEnumsAndKeyedValueObjects)
397+
{
398+
AddSmartEnumAndKeyedValueObjects(complexProperty.ComplexType, validateOnWrite, useConstructorForRead, converterLookup, configureEnumsAndKeyedValueObjects);
399+
AddNonKeyedValueObjectMembers(complexProperty.ComplexType);
400+
401+
AddConverterForScalarProperties(complexProperty.ComplexType, validateOnWrite, useConstructorForRead, converterLookup, configureEnumsAndKeyedValueObjects);
402+
AddConverterForComplexProperties(complexProperty.ComplexType, validateOnWrite, useConstructorForRead, converterLookup, configureEnumsAndKeyedValueObjects);
403+
}
340404
#endif
341405

342406
private static PropertyBuilder FindPropertyBuilder((EntityTypeBuilder?, OwnedNavigationBuilder?) builders, IMutableEntityType entityType, string propertyName)

test/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Tests.Sources/Extensions/EntityTypeBuilderExtensionsTests/AddValueObjectConverters.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ public void Should_add_converters_for_complex_types()
4646

4747
ValidateConverter(complexProperty.ComplexType, nameof(TestComplexType.TestEnum));
4848
}
49+
50+
[Fact]
51+
public void Should_add_converters_for_complex_types_inside_complex_type_configuration()
52+
{
53+
using var ctx = new TestDbContext(
54+
new DbContextOptionsBuilder<TestDbContext>().UseSqlite("DataSource=:memory:").Options,
55+
ValueConverterRegistration.ComplexTypeConfiguration);
56+
57+
var entityType = ctx.Model.FindEntityType(typeof(TestEntityWithComplexType)) ?? throw new Exception("Entity not found");
58+
var complexProperty = entityType.FindComplexProperty(nameof(TestEntityWithComplexType.TestComplexType)) ?? throw new Exception("Complex type property not found");
59+
60+
ValidateConverter(complexProperty.ComplexType, nameof(TestComplexType.TestEnum));
61+
}
4962
#endif
5063

5164
[Fact]

test/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Tests.Sources/TestEntities/TestDbContext.cs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
3333
{
3434
base.OnModelCreating(modelBuilder);
3535

36-
TestEntity_with_OwnedTypes.Configure(
37-
modelBuilder,
38-
_valueConverterRegistration == ValueConverterRegistration.EntityConfiguration);
39-
TestEntity_with_Enum_and_ValueObjects.Configure(
40-
modelBuilder,
41-
_valueConverterRegistration == ValueConverterRegistration.EntityConfiguration);
36+
var configureOnEntityTypeLevel = _valueConverterRegistration is ValueConverterRegistration.EntityConfiguration or ValueConverterRegistration.ComplexTypeConfiguration;
37+
38+
TestEntity_with_OwnedTypes.Configure(modelBuilder, configureOnEntityTypeLevel);
39+
TestEntity_with_Enum_and_ValueObjects.Configure(modelBuilder, configureOnEntityTypeLevel);
4240

4341
#if COMPLEX_TYPES
44-
TestEntityWithComplexType.Configure(
45-
modelBuilder,
46-
_valueConverterRegistration == ValueConverterRegistration.EntityConfiguration);
42+
TestEntityWithComplexType.Configure(modelBuilder, _valueConverterRegistration);
4743
#endif
4844

4945
if (_valueConverterRegistration == ValueConverterRegistration.OnModelCreating)

test/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Tests.Sources/TestEntities/TestEntityWithComplexType.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class TestEntityWithComplexType
1111

1212
public static void Configure(
1313
ModelBuilder modelBuilder,
14-
bool registerValueConverters)
14+
ValueConverterRegistration valueConverterRegistration)
1515
{
1616
modelBuilder.Entity<TestEntityWithComplexType>(builder =>
1717
{
@@ -20,9 +20,12 @@ public static void Configure(
2020
{
2121
b.IsRequired();
2222
b.Property(t => t.TestEnum);
23+
24+
if (valueConverterRegistration == ValueConverterRegistration.ComplexTypeConfiguration)
25+
b.AddValueObjectConverters(true);
2326
});
2427

25-
if (registerValueConverters)
28+
if (valueConverterRegistration == ValueConverterRegistration.EntityConfiguration)
2629
builder.AddValueObjectConverters(true);
2730
});
2831
}

test/Thinktecture.Runtime.Extensions.EntityFrameworkCore.Tests.Sources/TestEntities/ValueConverterRegistration.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ public enum ValueConverterRegistration
44
{
55
None,
66
OnModelCreating,
7-
EntityConfiguration
7+
EntityConfiguration,
8+
ComplexTypeConfiguration
89
}

0 commit comments

Comments
 (0)