diff --git a/src/Vogen/GenerateCastingOperators.cs b/src/Vogen/GenerateCastingOperators.cs index 63013b04ef..3bd42647d1 100644 --- a/src/Vogen/GenerateCastingOperators.cs +++ b/src/Vogen/GenerateCastingOperators.cs @@ -41,12 +41,25 @@ public static string GenerateImplementations(VoWorkItem item, TypeDeclarationSyn if (item.Config.FromPrimitiveCasting == CastOperator.Implicit) { - sb.AppendLine( - $$""" - public static implicit operator {{className}}({{itemUnderlyingType}} value) { - return new {{className}}(value); - } - """); + if (item.NormalizeInputMethod is not null) + { + sb.AppendLine( + $$""" + public static implicit operator {{className}}({{itemUnderlyingType}} value) { + return new {{className}}({{className}}.NormalizeInput(value)); + } + """); + + } + else + { + sb.AppendLine( + $$""" + public static implicit operator {{className}}({{itemUnderlyingType}} value) { + return new {{className}}(value); + } + """); + } } if (sb.Length == 0) diff --git a/tests/ConsumerTests/BugFix624.cs b/tests/ConsumerTests/BugFix624.cs new file mode 100644 index 0000000000..3458d75c64 --- /dev/null +++ b/tests/ConsumerTests/BugFix624.cs @@ -0,0 +1,36 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; +using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; + +namespace ConsumerTests.BugFixTests.BugFix639; + +[ValueObject(fromPrimitiveCasting: CastOperator.Implicit)] +public partial class C_With +{ + private static string NormalizeInput(string input) => input.ToUpper(); +} + +[ValueObject(fromPrimitiveCasting: CastOperator.Implicit)] +public partial class C_Without; + +/// +/// Fixes bug https://github.com/SteveDunn/Vogen/issues/639 where any +/// `NormalizeInput` method was not called when implicitly converting a primitive to a value object +/// +public class Tests +{ + [Fact] + public void Should_call_if_present() + { + C_With vo = "abc"; + vo.Value.Should().Be("ABC"); + } + + [Fact] + public void Should_not_call_if_not_present() + { + C_Without vo = "abc"; + vo.Value.Should().Be("abc"); + } +} diff --git a/tests/ConsumerTests/Casting/ForClasses.cs b/tests/ConsumerTests/Casting/ForClasses.cs index edf0632f48..7893e17216 100644 --- a/tests/ConsumerTests/Casting/ForClasses.cs +++ b/tests/ConsumerTests/Casting/ForClasses.cs @@ -46,4 +46,20 @@ public void Implicit_both_ways() Class_implicit_both_ways vo2 = prim; vo2.Should().Be(vo); } + + [Fact] + public void Implicit_both_ways_with_normalization() + { + using var _ = new AssertionScope(); + + var vo = Class_implicit_both_ways_with_normalization.From("abc"); + + string prim = vo; + + prim.Should().Be(vo.Value); + + Class_implicit_both_ways_with_normalization vo2 = prim; + vo2.Should().Be(vo); + vo2.Value.Should().Be("ABC"); + } } diff --git a/tests/ConsumerTests/Casting/ForStructs.cs b/tests/ConsumerTests/Casting/ForStructs.cs index 9e505fce8a..d358482404 100644 --- a/tests/ConsumerTests/Casting/ForStructs.cs +++ b/tests/ConsumerTests/Casting/ForStructs.cs @@ -46,4 +46,21 @@ public void Implicit_both_ways() Struct_implicit_both_ways vo2 = prim; vo2.Should().Be(vo); } + + [Fact] + public void Implicit_both_ways_with_normalization() + { + using var _ = new AssertionScope(); + + var vo = Struct_implicit_both_ways_with_normalization.From("abc"); + + string prim = vo; + + prim.Should().Be(vo.Value); + + Struct_implicit_both_ways_with_normalization vo2 = prim; + vo2.Should().Be(vo); + vo2.Value.Should().Be("ABC"); + } + } diff --git a/tests/ConsumerTests/Casting/Types.cs b/tests/ConsumerTests/Casting/Types.cs index 566700d95b..e4875a347e 100644 --- a/tests/ConsumerTests/Casting/Types.cs +++ b/tests/ConsumerTests/Casting/Types.cs @@ -15,6 +15,12 @@ public partial class Class_implicit_both_ways { } +[ValueObject(typeof(string), toPrimitiveCasting: CastOperator.Implicit, fromPrimitiveCasting: CastOperator.Implicit)] +public partial class Class_implicit_both_ways_with_normalization +{ + private static string NormalizeInput(string input) => input.ToUpper(); +} + [ValueObject(toPrimitiveCasting: CastOperator.None, fromPrimitiveCasting: CastOperator.None)] public partial class Class_default_generic { @@ -35,6 +41,12 @@ public partial class Struct_implicit_both_ways { } +[ValueObject(typeof(string), toPrimitiveCasting: CastOperator.Implicit, fromPrimitiveCasting: CastOperator.Implicit)] +public partial class Struct_implicit_both_ways_with_normalization +{ + private static string NormalizeInput(string input) => input.ToUpper(); +} + [ValueObject(toPrimitiveCasting: CastOperator.None, fromPrimitiveCasting: CastOperator.None)] public partial class Struct_default_generic {