diff --git a/samples/Thinktecture.Runtime.Extensions.Samples/EnumLikeClasses/EnumLikeClassDemos.cs b/samples/Thinktecture.Runtime.Extensions.Samples/EnumLikeClasses/EnumLikeClassDemos.cs index 0e55beef..07e7010f 100644 --- a/samples/Thinktecture.Runtime.Extensions.Samples/EnumLikeClasses/EnumLikeClassDemos.cs +++ b/samples/Thinktecture.Runtime.Extensions.Samples/EnumLikeClasses/EnumLikeClassDemos.cs @@ -22,6 +22,9 @@ private static void DemoForNonValidatableEnum(ILogger logger) var productType = ProductType.Get("Groceries"); logger.Information("Product type: {type}", productType); + productType = (ProductType)"Groceries"; + logger.Information("Explicitly casted product type: {type}", productType); + if (ProductType.TryGet("Housewares", out var housewares)) logger.Information("Product type {type} with TryGet found", housewares); diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EnumSourceGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EnumSourceGenerator.cs index 16a71b7c..67a2d417 100644 --- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EnumSourceGenerator.cs +++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/EnumSourceGenerator.cs @@ -119,6 +119,7 @@ internal static void ModuleInit() GeneratedTryGet(); GenerateImplicitConversion(); + GenerateExplicitConversion(); GenerateEqualityOperators(); GenerateTypedEquals(); @@ -216,7 +217,7 @@ private void GenerateImplicitConversion() _sb.Append($@" /// - /// Implicit conversion to the type of . + /// Implicit conversion to the type . /// /// Item to covert. /// The of provided or default if is null. @@ -239,6 +240,22 @@ private void GenerateImplicitConversion() }}"); } + private void GenerateExplicitConversion() + { + _sb.Append($@" + + /// + /// Explicit conversion from the type . + /// + /// Value to covert. + /// An instance of if the is a known item or implements . + [return: NotNullIfNotNull(""{_state.KeyArgumentName}"")] + public static explicit operator {_state.EnumIdentifier}{_state.NullableQuestionMarkEnum}({_state.KeyType}{_state.NullableQuestionMarkKey} {_state.KeyArgumentName}) + {{ + return {_state.EnumIdentifier}.Get({_state.KeyArgumentName}); + }}"); + } + private void GenerateTypedEquals() { _sb.Append($@" diff --git a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueTypeSourceGenerator.cs b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueTypeSourceGenerator.cs index 44174143..3b4408ad 100644 --- a/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueTypeSourceGenerator.cs +++ b/src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/ValueTypeSourceGenerator.cs @@ -123,6 +123,7 @@ internal static void ModuleInit() { GenerateFactoryMethod(_state.KeyMember); GenerateImplicitConversion(_state.KeyMember); + GenerateExplicitConversion(_state.KeyMember); } GenerateConstructor(); @@ -140,7 +141,7 @@ private void GenerateImplicitConversion(InstanceMemberInfo keyMember) _sb.Append($@" /// - /// Implicit conversion to the type of . + /// Implicit conversion to the type . /// /// Object to covert. /// The of provided or default if is null. @@ -163,6 +164,21 @@ private void GenerateImplicitConversion(InstanceMemberInfo keyMember) }}"); } + private void GenerateExplicitConversion(InstanceMemberInfo keyMember) + { + _sb.Append($@" + + /// + /// Explicit conversion from the type . + /// + /// Value to covert. + /// An instance of . + public static explicit operator {_state.TypeIdentifier}({keyMember.Type} {keyMember.ArgumentName}) + {{ + return {_state.TypeIdentifier}.Create({keyMember.ArgumentName}); + }}"); + } + private void GenerateFactoryMethod(InstanceMemberInfo keyMember) { _sb.Append($@" diff --git a/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/EnumSourceGeneratorTests.cs b/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/EnumSourceGeneratorTests.cs index 8803a0ef..71df8dd0 100644 --- a/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/EnumSourceGeneratorTests.cs +++ b/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/EnumSourceGeneratorTests.cs @@ -62,7 +62,7 @@ internal static void ModuleInit() Expression> convertToKeyExpression = item => item.Key; var enumType = typeof(TestEnum); - var metadata = new ValueTypeMetadata(enumType, typeof(string), convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); + var metadata = new ValueTypeMetadata(enumType, typeof(string), false, convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); ValueTypeMetadataLookup.AddMetadata(enumType, metadata); } @@ -144,7 +144,7 @@ public static bool TryGet([AllowNull] string key, [MaybeNullWhen(false)] out Tes } /// - /// Implicit conversion to the type of . + /// Implicit conversion to the type . /// /// Item to covert. /// The of provided or default if is null. @@ -154,6 +154,17 @@ public static bool TryGet([AllowNull] string key, [MaybeNullWhen(false)] out Tes return item is null ? default : item.Key; } + /// + /// Explicit conversion from the type . + /// + /// Value to covert. + /// An instance of if the is a known item or implements . + [return: NotNullIfNotNull(""key"")] + public static explicit operator TestEnum?(string? key) + { + return TestEnum.Get(key); + } + /// /// Compares to instances of . /// @@ -336,7 +347,7 @@ internal static void ModuleInit() Expression> convertToKeyExpression = item => item.Key; var enumType = typeof(TestEnum); - var metadata = new ValueTypeMetadata(enumType, typeof(string), convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); + var metadata = new ValueTypeMetadata(enumType, typeof(string), true, convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); ValueTypeMetadataLookup.AddMetadata(enumType, metadata); } @@ -447,7 +458,7 @@ public static bool TryGet([AllowNull] string key, [MaybeNullWhen(false)] out Tes } /// - /// Implicit conversion to the type of . + /// Implicit conversion to the type . /// /// Item to covert. /// The of provided or default if is null. @@ -457,6 +468,17 @@ public static bool TryGet([AllowNull] string key, [MaybeNullWhen(false)] out Tes return item is null ? default : item.Key; } + /// + /// Explicit conversion from the type . + /// + /// Value to covert. + /// An instance of if the is a known item or implements . + [return: NotNullIfNotNull(""key"")] + public static explicit operator TestEnum?(string? key) + { + return TestEnum.Get(key); + } + /// /// Compares to instances of . /// @@ -609,7 +631,7 @@ internal static void ModuleInit() Expression> convertToKeyExpression = item => item.Key; var enumType = typeof(TestEnum); - var metadata = new ValueTypeMetadata(enumType, typeof(string), convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); + var metadata = new ValueTypeMetadata(enumType, typeof(string), true, convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); ValueTypeMetadataLookup.AddMetadata(enumType, metadata); } @@ -717,7 +739,7 @@ public static bool TryGet([AllowNull] string key, [MaybeNullWhen(false)] out Tes } /// - /// Implicit conversion to the type of . + /// Implicit conversion to the type . /// /// Item to covert. /// The of provided or default if is null. @@ -727,6 +749,17 @@ public static bool TryGet([AllowNull] string key, [MaybeNullWhen(false)] out Tes return item.Key; } + /// + /// Explicit conversion from the type . + /// + /// Value to covert. + /// An instance of if the is a known item or implements . + [return: NotNullIfNotNull(""key"")] + public static explicit operator TestEnum(string? key) + { + return TestEnum.Get(key); + } + /// /// Compares to instances of . /// @@ -898,7 +931,7 @@ internal static void ModuleInit() Expression> convertToKeyExpression = item => item.Name; var enumType = typeof(TestEnum); - var metadata = new ValueTypeMetadata(enumType, typeof(string), convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); + var metadata = new ValueTypeMetadata(enumType, typeof(string), true, convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); ValueTypeMetadataLookup.AddMetadata(enumType, metadata); } @@ -1009,7 +1042,7 @@ public static bool TryGet([AllowNull] string name, [MaybeNullWhen(false)] out Te } /// - /// Implicit conversion to the type of . + /// Implicit conversion to the type . /// /// Item to covert. /// The of provided or default if is null. @@ -1019,6 +1052,17 @@ public static bool TryGet([AllowNull] string name, [MaybeNullWhen(false)] out Te return item is null ? default : item.Name; } + /// + /// Explicit conversion from the type . + /// + /// Value to covert. + /// An instance of if the is a known item or implements . + [return: NotNullIfNotNull(""name"")] + public static explicit operator TestEnum?(string? name) + { + return TestEnum.Get(name); + } + /// /// Compares to instances of . /// diff --git a/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/ValueTypeSourceGeneratorTests.cs b/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/ValueTypeSourceGeneratorTests.cs index 79563312..86d751b1 100644 --- a/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/ValueTypeSourceGeneratorTests.cs +++ b/test/Thinktecture.Runtime.Extensions.SourceGenerator.Tests/SourceGeneratorTests/ValueTypeSourceGeneratorTests.cs @@ -295,7 +295,7 @@ internal static void ModuleInit() Expression> convertToKeyExpression = obj => obj.ReferenceField; var type = typeof(TestValueType); - var metadata = new ValueTypeMetadata(type, typeof(string), convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); + var metadata = new ValueTypeMetadata(type, typeof(string), false, convertFromKey, convertFromKeyExpression, convertToKey, convertToKeyExpression); ValueTypeMetadataLookup.AddMetadata(type, metadata); } @@ -330,7 +330,7 @@ public static bool TryCreate( static partial void ValidateFactoryArguments(ref string referenceField); /// - /// Implicit conversion to the type of . + /// Implicit conversion to the type . /// /// Object to covert. /// The of provided or default if is null. @@ -340,6 +340,16 @@ public static bool TryCreate( return obj is null ? default : obj.ReferenceField; } + /// + /// Explicit conversion from the type . + /// + /// Value to covert. + /// An instance of . + public static explicit operator TestValueType(string referenceField) + { + return TestValueType.Create(referenceField); + } + private TestValueType(string referenceField) { ValidateConstructorArguments(ref referenceField);