From cd4bf68ab89c0042f813e2c1dcc52ab002669c50 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Tue, 24 Jan 2023 22:36:01 +0000 Subject: [PATCH 01/47] Use ForAttributeWithMetadataName APIs Fix duplicate test problem Add new diagnostic for duplicate assembly attributes --- src/StronglyTypedIds/DiagnosticInfo.cs | 15 + .../InvalidBackingTypeDiagnostic.cs | 5 + .../Diagnostics/InvalidConverterDiagnostic.cs | 5 + .../InvalidImplementationsDiagnostic.cs | 5 +- .../MultipleAssemblyAttributeDiagnostic.cs | 15 + .../Diagnostics/NotPartialDiagnostic.cs | 5 + src/StronglyTypedIds/EquatableArray.cs | 105 +++++ src/StronglyTypedIds/HashCode.cs | 383 ++++++++++++++++++ src/StronglyTypedIds/ParentClass.cs | 2 +- src/StronglyTypedIds/Parser.cs | 354 +++++++--------- .../SourceGenerationHelper.cs | 16 +- .../StronglyTypedIdConfiguration.cs | 2 +- .../StronglyTypedIdGenerator.cs | 103 ++--- src/StronglyTypedIds/StructToGenerate.cs | 36 ++ test/StronglyTypedIds.Tests/EqualityTests.cs | 136 +++++++ ...ttributesGeneratesWithDefault.verified.txt | 254 ++++++++++++ .../SourceGenerationHelperSnapshotTests.cs | 5 + .../StronglyTypedIdGeneratorTests.cs | 18 + 18 files changed, 1193 insertions(+), 271 deletions(-) create mode 100644 src/StronglyTypedIds/DiagnosticInfo.cs create mode 100644 src/StronglyTypedIds/Diagnostics/MultipleAssemblyAttributeDiagnostic.cs create mode 100644 src/StronglyTypedIds/EquatableArray.cs create mode 100644 src/StronglyTypedIds/HashCode.cs create mode 100644 src/StronglyTypedIds/StructToGenerate.cs create mode 100644 test/StronglyTypedIds.Tests/EqualityTests.cs create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt diff --git a/src/StronglyTypedIds/DiagnosticInfo.cs b/src/StronglyTypedIds/DiagnosticInfo.cs new file mode 100644 index 000000000..8fd036237 --- /dev/null +++ b/src/StronglyTypedIds/DiagnosticInfo.cs @@ -0,0 +1,15 @@ +using Microsoft.CodeAnalysis; + +namespace StronglyTypedIds; + +internal sealed record DiagnosticInfo +{ + public DiagnosticInfo(DiagnosticDescriptor descriptor, Location location) + { + Descriptor = descriptor; + Location = location; + } + + public DiagnosticDescriptor Descriptor { get; } + public Location Location { get; } +} \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/InvalidBackingTypeDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidBackingTypeDiagnostic.cs index b052e0302..44b594690 100644 --- a/src/StronglyTypedIds/Diagnostics/InvalidBackingTypeDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/InvalidBackingTypeDiagnostic.cs @@ -13,5 +13,10 @@ public static Diagnostic Create(SyntaxNode currentNode) => new DiagnosticDescriptor( Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), currentNode.GetLocation()); + + public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) + => new(new DiagnosticDescriptor( + Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), + currentNode.GetLocation()); } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/InvalidConverterDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidConverterDiagnostic.cs index bf601c518..a20b771db 100644 --- a/src/StronglyTypedIds/Diagnostics/InvalidConverterDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/InvalidConverterDiagnostic.cs @@ -13,5 +13,10 @@ public static Diagnostic Create(SyntaxNode currentNode) => new DiagnosticDescriptor( Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), currentNode.GetLocation()); + + public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) + => new(new DiagnosticDescriptor( + Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), + currentNode.GetLocation()); } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/InvalidImplementationsDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidImplementationsDiagnostic.cs index dc4388613..c42865151 100644 --- a/src/StronglyTypedIds/Diagnostics/InvalidImplementationsDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/InvalidImplementationsDiagnostic.cs @@ -8,9 +8,8 @@ internal static class InvalidImplementationsDiagnostic internal const string Message = "The StronglyTypedIdImplementations value provided is not a valid combination of flags"; internal const string Title = "Invalid implementations value"; - public static Diagnostic Create(SyntaxNode currentNode) => - Diagnostic.Create( - new DiagnosticDescriptor( + public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) + => new(new DiagnosticDescriptor( Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), currentNode.GetLocation()); } diff --git a/src/StronglyTypedIds/Diagnostics/MultipleAssemblyAttributeDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/MultipleAssemblyAttributeDiagnostic.cs new file mode 100644 index 000000000..dfadb4f1c --- /dev/null +++ b/src/StronglyTypedIds/Diagnostics/MultipleAssemblyAttributeDiagnostic.cs @@ -0,0 +1,15 @@ +using Microsoft.CodeAnalysis; + +namespace StronglyTypedIds.Diagnostics; + +internal static class MultipleAssemblyAttributeDiagnostic +{ + internal const string Id = "STI6"; + internal const string Message = "You may only have one instance of the StronglyTypedIdDefaults assembly attribute"; + internal const string Title = "Multiple assembly attributes"; + + public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) => + new(new DiagnosticDescriptor( + Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), + currentNode.GetLocation()); +} \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/NotPartialDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/NotPartialDiagnostic.cs index 6c8435da1..c1a66d922 100644 --- a/src/StronglyTypedIds/Diagnostics/NotPartialDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/NotPartialDiagnostic.cs @@ -13,5 +13,10 @@ public static Diagnostic Create(SyntaxNode currentNode) => new DiagnosticDescriptor( Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), currentNode.GetLocation()); + + public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) + => new(new DiagnosticDescriptor( + Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), + currentNode.GetLocation()); } } \ No newline at end of file diff --git a/src/StronglyTypedIds/EquatableArray.cs b/src/StronglyTypedIds/EquatableArray.cs new file mode 100644 index 000000000..33d48db8c --- /dev/null +++ b/src/StronglyTypedIds/EquatableArray.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace StronglyTypedIds; + +/// +/// An immutable, equatable array. This is equivalent to but with value equality support. +/// +/// The type of values in the array. +internal readonly struct EquatableArray : IEquatable>, IEnumerable + where T : IEquatable +{ + public static readonly EquatableArray Empty = new(Array.Empty()); + + /// + /// The underlying array. + /// + private readonly T[]? _array; + + /// + /// Creates a new instance. + /// + /// The input to wrap. + public EquatableArray(T[] array) + { + _array = array; + } + + /// + public bool Equals(EquatableArray array) + { + return AsSpan().SequenceEqual(array.AsSpan()); + } + + /// + public override bool Equals(object? obj) + { + return obj is EquatableArray array && Equals(this, array); + } + + /// + public override int GetHashCode() + { + if (_array is not T[] array) + { + return 0; + } + + HashCode hashCode = default; + + foreach (T item in array) + { + hashCode.Add(item); + } + + return hashCode.ToHashCode(); + } + + /// + /// Returns a wrapping the current items. + /// + /// A wrapping the current items. + public ReadOnlySpan AsSpan() + { + return _array.AsSpan(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)(_array ?? Array.Empty())).GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)(_array ?? Array.Empty())).GetEnumerator(); + } + + public int Count => _array?.Length ?? 0; + + /// + /// Checks whether two values are the same. + /// + /// The first value. + /// The second value. + /// Whether and are equal. + public static bool operator ==(EquatableArray left, EquatableArray right) + { + return left.Equals(right); + } + + /// + /// Checks whether two values are not the same. + /// + /// The first value. + /// The second value. + /// Whether and are not equal. + public static bool operator !=(EquatableArray left, EquatableArray right) + { + return !left.Equals(right); + } +} \ No newline at end of file diff --git a/src/StronglyTypedIds/HashCode.cs b/src/StronglyTypedIds/HashCode.cs new file mode 100644 index 000000000..4a2ca9ea3 --- /dev/null +++ b/src/StronglyTypedIds/HashCode.cs @@ -0,0 +1,383 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace StronglyTypedIds; + +/// +/// Polyfill for .NET 6 HashCode +/// +internal struct HashCode +{ + private static readonly uint s_seed = GenerateGlobalSeed(); + + private const uint Prime1 = 2654435761U; + private const uint Prime2 = 2246822519U; + private const uint Prime3 = 3266489917U; + private const uint Prime4 = 668265263U; + private const uint Prime5 = 374761393U; + + private uint _v1, _v2, _v3, _v4; + private uint _queue1, _queue2, _queue3; + private uint _length; + + private static uint GenerateGlobalSeed() + { + var buffer = new byte[sizeof(uint)]; + new Random().NextBytes(buffer); + return BitConverter.ToUInt32(buffer, 0); + } + + public static int Combine(T1 value1) + { + // Provide a way of diffusing bits from something with a limited + // input hash space. For example, many enums only have a few + // possible hashes, only using the bottom few bits of the code. Some + // collections are built on the assumption that hashes are spread + // over a larger space, so diffusing the bits may help the + // collection work more efficiently. + + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + + uint hash = MixEmptyState(); + hash += 4; + + hash = QueueRound(hash, hc1); + + hash = MixFinal(hash); + return (int)hash; + } + + public static int Combine(T1 value1, T2 value2) + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + + uint hash = MixEmptyState(); + hash += 8; + + hash = QueueRound(hash, hc1); + hash = QueueRound(hash, hc2); + + hash = MixFinal(hash); + return (int)hash; + } + + public static int Combine(T1 value1, T2 value2, T3 value3) + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + + uint hash = MixEmptyState(); + hash += 12; + + hash = QueueRound(hash, hc1); + hash = QueueRound(hash, hc2); + hash = QueueRound(hash, hc3); + + hash = MixFinal(hash); + return (int)hash; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4) + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + uint hash = MixState(v1, v2, v3, v4); + hash += 16; + + hash = MixFinal(hash); + return (int)hash; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + uint hc5 = (uint)(value5?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + uint hash = MixState(v1, v2, v3, v4); + hash += 20; + + hash = QueueRound(hash, hc5); + + hash = MixFinal(hash); + return (int)hash; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + uint hc5 = (uint)(value5?.GetHashCode() ?? 0); + uint hc6 = (uint)(value6?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + uint hash = MixState(v1, v2, v3, v4); + hash += 24; + + hash = QueueRound(hash, hc5); + hash = QueueRound(hash, hc6); + + hash = MixFinal(hash); + return (int)hash; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + uint hc5 = (uint)(value5?.GetHashCode() ?? 0); + uint hc6 = (uint)(value6?.GetHashCode() ?? 0); + uint hc7 = (uint)(value7?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + uint hash = MixState(v1, v2, v3, v4); + hash += 28; + + hash = QueueRound(hash, hc5); + hash = QueueRound(hash, hc6); + hash = QueueRound(hash, hc7); + + hash = MixFinal(hash); + return (int)hash; + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8) + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + uint hc5 = (uint)(value5?.GetHashCode() ?? 0); + uint hc6 = (uint)(value6?.GetHashCode() ?? 0); + uint hc7 = (uint)(value7?.GetHashCode() ?? 0); + uint hc8 = (uint)(value8?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + v1 = Round(v1, hc5); + v2 = Round(v2, hc6); + v3 = Round(v3, hc7); + v4 = Round(v4, hc8); + + uint hash = MixState(v1, v2, v3, v4); + hash += 32; + + hash = MixFinal(hash); + return (int)hash; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4) + { + v1 = s_seed + Prime1 + Prime2; + v2 = s_seed + Prime2; + v3 = s_seed; + v4 = s_seed - Prime1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint Round(uint hash, uint input) + { + return RotateLeft(hash + input * Prime2, 13) * Prime1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint QueueRound(uint hash, uint queuedValue) + { + return RotateLeft(hash + queuedValue * Prime3, 17) * Prime4; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint MixState(uint v1, uint v2, uint v3, uint v4) + { + return RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18); + } + + private static uint MixEmptyState() + { + return s_seed + Prime5; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint MixFinal(uint hash) + { + hash ^= hash >> 15; + hash *= Prime2; + hash ^= hash >> 13; + hash *= Prime3; + hash ^= hash >> 16; + return hash; + } + + public void Add(T value) + { + Add(value?.GetHashCode() ?? 0); + } + + public void Add(T value, IEqualityComparer? comparer) + { + Add(value is null ? 0 : (comparer?.GetHashCode(value) ?? value.GetHashCode())); + } + + private void Add(int value) + { + // The original xxHash works as follows: + // 0. Initialize immediately. We can't do this in a struct (no + // default ctor). + // 1. Accumulate blocks of length 16 (4 uints) into 4 accumulators. + // 2. Accumulate remaining blocks of length 4 (1 uint) into the + // hash. + // 3. Accumulate remaining blocks of length 1 into the hash. + + // There is no need for #3 as this type only accepts ints. _queue1, + // _queue2 and _queue3 are basically a buffer so that when + // ToHashCode is called we can execute #2 correctly. + + // We need to initialize the xxHash32 state (_v1 to _v4) lazily (see + // #0) nd the last place that can be done if you look at the + // original code is just before the first block of 16 bytes is mixed + // in. The xxHash32 state is never used for streams containing fewer + // than 16 bytes. + + // To see what's really going on here, have a look at the Combine + // methods. + + uint val = (uint)value; + + // Storing the value of _length locally shaves of quite a few bytes + // in the resulting machine code. + uint previousLength = _length++; + uint position = previousLength % 4; + + // Switch can't be inlined. + + if (position == 0) + _queue1 = val; + else if (position == 1) + _queue2 = val; + else if (position == 2) + _queue3 = val; + else // position == 3 + { + if (previousLength == 3) + Initialize(out _v1, out _v2, out _v3, out _v4); + + _v1 = Round(_v1, _queue1); + _v2 = Round(_v2, _queue2); + _v3 = Round(_v3, _queue3); + _v4 = Round(_v4, val); + } + } + + public int ToHashCode() + { + // Storing the value of _length locally shaves of quite a few bytes + // in the resulting machine code. + uint length = _length; + + // position refers to the *next* queue position in this method, so + // position == 1 means that _queue1 is populated; _queue2 would have + // been populated on the next call to Add. + uint position = length % 4; + + // If the length is less than 4, _v1 to _v4 don't contain anything + // yet. xxHash32 treats this differently. + + uint hash = length < 4 ? MixEmptyState() : MixState(_v1, _v2, _v3, _v4); + + // _length is incremented once per Add(Int32) and is therefore 4 + // times too small (xxHash length is in bytes, not ints). + + hash += length * 4; + + // Mix what remains in the queue + + // Switch can't be inlined right now, so use as few branches as + // possible by manually excluding impossible scenarios (position > 1 + // is always false if position is not > 0). + if (position > 0) + { + hash = QueueRound(hash, _queue1); + if (position > 1) + { + hash = QueueRound(hash, _queue2); + if (position > 2) + hash = QueueRound(hash, _queue3); + } + } + + hash = MixFinal(hash); + return (int)hash; + } + +#pragma warning disable 0809 + // Obsolete member 'memberA' overrides non-obsolete member 'memberB'. + // Disallowing GetHashCode and Equals is by design + + // * We decided to not override GetHashCode() to produce the hash code + // as this would be weird, both naming-wise as well as from a + // behavioral standpoint (GetHashCode() should return the object's + // hash code, not the one being computed). + + // * Even though ToHashCode() can be called safely multiple times on + // this implementation, it is not part of the contract. If the + // implementation has to change in the future we don't want to worry + // about people who might have incorrectly used this type. + + [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", error: true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => throw new NotSupportedException("Hash code not supported"); + + [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object? obj) => throw new NotSupportedException("Equality not supported"); +#pragma warning restore 0809 + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint RotateLeft(uint value, int offset) + => (value << offset) | (value >> (32 - offset)); +} \ No newline at end of file diff --git a/src/StronglyTypedIds/ParentClass.cs b/src/StronglyTypedIds/ParentClass.cs index 012c41274..01f6036ff 100644 --- a/src/StronglyTypedIds/ParentClass.cs +++ b/src/StronglyTypedIds/ParentClass.cs @@ -1,6 +1,6 @@ namespace StronglyTypedIds; -internal class ParentClass +internal record ParentClass { public ParentClass(string keyword, string name, string constraints, ParentClass? child) { diff --git a/src/StronglyTypedIds/Parser.cs b/src/StronglyTypedIds/Parser.cs index 39fc96f93..fcc71d0af 100644 --- a/src/StronglyTypedIds/Parser.cs +++ b/src/StronglyTypedIds/Parser.cs @@ -14,255 +14,183 @@ internal static class Parser public const string StronglyTypedIdAttribute = "StronglyTypedIds.StronglyTypedIdAttribute"; public const string StronglyTypedIdDefaultsAttribute = "StronglyTypedIds.StronglyTypedIdDefaultsAttribute"; - public static bool IsStructTargetForGeneration(SyntaxNode node) - => node is StructDeclarationSyntax m && m.AttributeLists.Count > 0; - - public static bool IsAttributeTargetForGeneration(SyntaxNode node) - => node is AttributeListSyntax attributeList - && attributeList.Target is not null - && attributeList.Target.Identifier.IsKind(SyntaxKind.AssemblyKeyword); - - public static StructDeclarationSyntax? GetStructSemanticTargetForGeneration(GeneratorSyntaxContext context) + public static Result<(StructToGenerate info, bool valid)> GetStructSemanticTarget(GeneratorAttributeSyntaxContext ctx, CancellationToken ct) { - // we know the node is a EnumDeclarationSyntax thanks to IsSyntaxTargetForGeneration - var structDeclarationSyntax = (StructDeclarationSyntax)context.Node; - - // loop through all the attributes on the method - foreach (AttributeListSyntax attributeListSyntax in structDeclarationSyntax.AttributeLists) + var structSymbol = ctx.TargetSymbol as INamedTypeSymbol; + if (structSymbol is null) { - foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) - { - if (ModelExtensions.GetSymbolInfo(context.SemanticModel, attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) - { - // weird, we couldn't get the symbol, ignore it - continue; - } - - INamedTypeSymbol attributeContainingTypeSymbol = attributeSymbol.ContainingType; - string fullName = attributeContainingTypeSymbol.ToDisplayString(); - - // Is the attribute the [StronglyTypedId] attribute? - if (fullName == StronglyTypedIdAttribute) - { - // return the enum - return structDeclarationSyntax; - } - } + return Result.Fail(); } - // we didn't find the attribute we were looking for - return null; - } + var structSyntax = (StructDeclarationSyntax)ctx.TargetNode; - public static AttributeSyntax? GetAssemblyAttributeSemanticTargetForGeneration(GeneratorSyntaxContext context) - { - // we know the node is a AttributeListSyntax thanks to IsSyntaxTargetForGeneration - var attributeListSyntax = (AttributeListSyntax)context.Node; + var hasMisconfiguredInput = false; + List? diagnostics = null; + StronglyTypedIdConfiguration? config = null; - // loop through all the attributes in the list - foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) + foreach (AttributeData attribute in structSymbol.GetAttributes()) { - if (ModelExtensions.GetSymbolInfo(context.SemanticModel, attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) + if (!((attribute.AttributeClass?.Name == "StronglyTypedIdAttribute" || + attribute.AttributeClass?.Name == "StronglyTypedId") && + attribute.AttributeClass.ToDisplayString() == StronglyTypedIdAttribute)) { - // weird, we couldn't get the symbol, ignore it + // wrong attribute continue; } - INamedTypeSymbol attributeContainingTypeSymbol = attributeSymbol.ContainingType; - string fullName = attributeContainingTypeSymbol.ToDisplayString(); - - // Is the attribute the [StronglyTypedIdDefaultsAttribute] attribute? - if (fullName == StronglyTypedIdDefaultsAttribute) - { - // return the attribute - return attributeSyntax; - } - } - - // we didn't find the attribute we were looking for - return null; - } - - public static List<(string Name, string NameSpace, StronglyTypedIdConfiguration Config, ParentClass? Parent)> GetTypesToGenerate( - Compilation compilation, - ImmutableArray targets, - Action reportDiagnostic, - CancellationToken ct) - { - var idsToGenerate = new List<(string Name, string NameSpace, StronglyTypedIdConfiguration Config, ParentClass? Parent)>(); - INamedTypeSymbol? idAttribute = compilation.GetTypeByMetadataName(StronglyTypedIdAttribute); - if (idAttribute == null) - { - // nothing to do if this type isn't available - return idsToGenerate; - } - - foreach (StructDeclarationSyntax structDeclarationSyntax in targets) - { - // stop if we're asked to - ct.ThrowIfCancellationRequested(); - - SemanticModel semanticModel = compilation.GetSemanticModel(structDeclarationSyntax.SyntaxTree); - if (semanticModel.GetDeclaredSymbol(structDeclarationSyntax) is not INamedTypeSymbol structSymbol) - { - // something went wrong - continue; - } - - StronglyTypedIdConfiguration? config = null; - var hasMisconfiguredInput = false; + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default; + StronglyTypedIdConverter converter = StronglyTypedIdConverter.Default; + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default; - foreach (AttributeData attribute in structSymbol.GetAttributes()) + if (!attribute.ConstructorArguments.IsEmpty) { - if (!idAttribute.Equals(attribute.AttributeClass, SymbolEqualityComparer.Default)) - { - continue; - } - - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default; - StronglyTypedIdConverter converter = StronglyTypedIdConverter.Default; - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default; + // make sure we don't have any errors + ImmutableArray args = attribute.ConstructorArguments; - if (!attribute.ConstructorArguments.IsEmpty) + foreach (TypedConstant arg in args) { - // make sure we don't have any errors - ImmutableArray args = attribute.ConstructorArguments; - - foreach (TypedConstant arg in args) + if (arg.Kind == TypedConstantKind.Error) { - if (arg.Kind == TypedConstantKind.Error) - { - // have an error, so don't try and do any generation - hasMisconfiguredInput = true; - } + // have an error, so don't try and do any generation + hasMisconfiguredInput = true; } + } - switch (args.Length) - { - case 3: - implementations = (StronglyTypedIdImplementations)args[2].Value!; - goto case 2; - case 2: - converter = (StronglyTypedIdConverter)args[1].Value!; - goto case 1; - case 1: - backingType = (StronglyTypedIdBackingType)args[0].Value!; - break; - } + switch (args.Length) + { + case 3: + implementations = (StronglyTypedIdImplementations)args[2].Value!; + goto case 2; + case 2: + converter = (StronglyTypedIdConverter)args[1].Value!; + goto case 1; + case 1: + backingType = (StronglyTypedIdBackingType)args[0].Value!; + break; } + } - if (!attribute.NamedArguments.IsEmpty) + if (!attribute.NamedArguments.IsEmpty) + { + foreach (KeyValuePair arg in attribute.NamedArguments) { - foreach (KeyValuePair arg in attribute.NamedArguments) + TypedConstant typedConstant = arg.Value; + if (typedConstant.Kind == TypedConstantKind.Error) { - TypedConstant typedConstant = arg.Value; - if (typedConstant.Kind == TypedConstantKind.Error) - { - hasMisconfiguredInput = true; - } - else + hasMisconfiguredInput = true; + } + else + { + switch (arg.Key) { - switch (arg.Key) - { - case "backingType": - backingType = (StronglyTypedIdBackingType)typedConstant.Value!; - break; - case "converters": - converter = (StronglyTypedIdConverter)typedConstant.Value!; - break; - case "implementations": - implementations = (StronglyTypedIdImplementations)typedConstant.Value!; - break; - } + case "backingType": + backingType = (StronglyTypedIdBackingType)typedConstant.Value!; + break; + case "converters": + converter = (StronglyTypedIdConverter)typedConstant.Value!; + break; + case "implementations": + implementations = (StronglyTypedIdImplementations)typedConstant.Value!; + break; } } - - - } - - if (hasMisconfiguredInput) - { - // skip further generator execution and let compiler generate the errors - break; - } - - if (!converter.IsValidFlags()) - { - reportDiagnostic(InvalidConverterDiagnostic.Create(structDeclarationSyntax)); - } - - if (!Enum.IsDefined(typeof(StronglyTypedIdBackingType), backingType)) - { - reportDiagnostic(InvalidBackingTypeDiagnostic.Create(structDeclarationSyntax)); - } - - if (!implementations.IsValidFlags()) - { - reportDiagnostic(InvalidImplementationsDiagnostic.Create(structDeclarationSyntax)); } + } - config = new StronglyTypedIdConfiguration(backingType, converter, implementations); + if (hasMisconfiguredInput) + { + // skip further generator execution and let compiler generate the errors break; } - if (config is null || hasMisconfiguredInput) + if (!converter.IsValidFlags()) { - continue; // name clash, or error + diagnostics ??= new(); + diagnostics.Add(InvalidConverterDiagnostic.CreateInfo(structSyntax)); } - var hasPartialModifier = false; - foreach (var modifier in structDeclarationSyntax.Modifiers) + if (!Enum.IsDefined(typeof(StronglyTypedIdBackingType), backingType)) { - if (modifier.IsKind(SyntaxKind.PartialKeyword)) - { - hasPartialModifier = true; - break; - } + diagnostics ??= new(); + diagnostics.Add(InvalidBackingTypeDiagnostic.CreateInfo(structSyntax)); } - if (!hasPartialModifier) + if (!implementations.IsValidFlags()) { - reportDiagnostic(NotPartialDiagnostic.Create(structDeclarationSyntax)); + diagnostics ??= new(); + diagnostics.Add(InvalidImplementationsDiagnostic.CreateInfo(structSyntax)); } - string nameSpace = GetNameSpace(structDeclarationSyntax); - var parentClass = GetParentClasses(structDeclarationSyntax); - var name = structSymbol.Name; - - idsToGenerate.Add((Name: name, NameSpace: nameSpace, Config: config.Value, Parent: parentClass)); + config = new StronglyTypedIdConfiguration(backingType, converter, implementations); + break; } - return idsToGenerate; - } + if (config is null || hasMisconfiguredInput) + { + var errors = diagnostics is null + ? EquatableArray.Empty + : new EquatableArray(diagnostics.ToArray()); + return new Result<(StructToGenerate, bool)>((default, false), errors); + } - public static StronglyTypedIdConfiguration? GetDefaults( - ImmutableArray defaults, - Compilation compilation, - Action reportDiagnostic) - { - if (defaults.IsDefaultOrEmpty) + var hasPartialModifier = false; + foreach (var modifier in structSyntax.Modifiers) { - // No global defaults - return null; + if (modifier.IsKind(SyntaxKind.PartialKeyword)) + { + hasPartialModifier = true; + break; + } } - var assemblyAttributes = compilation.Assembly.GetAttributes(); - if (assemblyAttributes.IsDefaultOrEmpty) + if (!hasPartialModifier) { - return null; + diagnostics ??= new(); + diagnostics.Add(NotPartialDiagnostic.CreateInfo(structSyntax)); } - INamedTypeSymbol? defaultsAttribute = compilation.GetTypeByMetadataName(StronglyTypedIdDefaultsAttribute); - if (defaultsAttribute is null) + string nameSpace = GetNameSpace(structSyntax); + ParentClass? parentClass = GetParentClasses(structSyntax); + var name = structSymbol.Name; + + var errs = diagnostics is null + ? EquatableArray.Empty + : new EquatableArray(diagnostics.ToArray()); + var toGenerate = new StructToGenerate(name: name, nameSpace: nameSpace, config: config.Value, parent: parentClass); + return new Result<(StructToGenerate, bool)>((toGenerate, true), errs); + } + + public static Result<(StronglyTypedIdConfiguration defaults, bool valid)> GetDefaults( + GeneratorAttributeSyntaxContext ctx, CancellationToken ct) + { + var assemblyAttributes = ctx.TargetSymbol.GetAttributes(); + if (assemblyAttributes.IsDefaultOrEmpty) { - // The attribute isn't part of the compilation for some reason... - return null; + return Result.Fail(); } + // We only return the first config that we find + StronglyTypedIdConfiguration? config = null; + List? diagnostics = null; + foreach (AttributeData attribute in assemblyAttributes) { - if (!defaultsAttribute.Equals(attribute.AttributeClass, SymbolEqualityComparer.Default)) + if (!((attribute.AttributeClass?.Name == "StronglyTypedIdDefaultsAttribute" || + attribute.AttributeClass?.Name == "StronglyTypedIdDefaults") && + attribute.AttributeClass.ToDisplayString() == StronglyTypedIdDefaultsAttribute)) { + // wrong attribute + continue; + } + + if (config.HasValue) + { + if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } s) + { + diagnostics ??= new(); + diagnostics.Add(MultipleAssemblyAttributeDiagnostic.CreateInfo(s)); + } + continue; } @@ -270,12 +198,12 @@ public static bool IsAttributeTargetForGeneration(SyntaxNode node) StronglyTypedIdConverter converter = StronglyTypedIdConverter.Default; StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default; bool hasMisconfiguredInput = false; - + if (!attribute.ConstructorArguments.IsEmpty) { // make sure we don't have any errors ImmutableArray args = attribute.ConstructorArguments; - + foreach (TypedConstant arg in args) { if (arg.Kind == TypedConstantKind.Error) @@ -284,7 +212,7 @@ public static bool IsAttributeTargetForGeneration(SyntaxNode node) hasMisconfiguredInput = true; } } - + switch (args.Length) { case 3: @@ -298,7 +226,7 @@ public static bool IsAttributeTargetForGeneration(SyntaxNode node) break; } } - + if (!attribute.NamedArguments.IsEmpty) { foreach (KeyValuePair arg in attribute.NamedArguments) @@ -325,45 +253,55 @@ public static bool IsAttributeTargetForGeneration(SyntaxNode node) } } } - + if (hasMisconfiguredInput) { // skip further generator execution and let compiler generate the errors break; } - + SyntaxNode? syntax = null; + if (!converter.IsValidFlags()) { syntax = attribute.ApplicationSyntaxReference?.GetSyntax(); if (syntax is not null) { - reportDiagnostic(InvalidConverterDiagnostic.Create(syntax)); + diagnostics ??= new(); + diagnostics.Add(InvalidConverterDiagnostic.CreateInfo(syntax)); } } - + if (!Enum.IsDefined(typeof(StronglyTypedIdBackingType), backingType)) { syntax ??= attribute.ApplicationSyntaxReference?.GetSyntax(); if (syntax is not null) { - reportDiagnostic(InvalidBackingTypeDiagnostic.Create(syntax)); + diagnostics ??= new(); + diagnostics.Add(InvalidBackingTypeDiagnostic.CreateInfo(syntax)); } } - + if (!implementations.IsValidFlags()) { syntax ??= attribute.ApplicationSyntaxReference?.GetSyntax(); if (syntax is not null) { - reportDiagnostic(InvalidImplementationsDiagnostic.Create(syntax)); + diagnostics ??= new(); + diagnostics.Add(InvalidImplementationsDiagnostic.CreateInfo(syntax)); } } - return new StronglyTypedIdConfiguration(backingType, converter, implementations); + config = new StronglyTypedIdConfiguration(backingType, converter, implementations); } - return null; + var errors = diagnostics is null + ? EquatableArray.Empty + : new EquatableArray(diagnostics.ToArray()); + + return config.HasValue + ? new Result<(StronglyTypedIdConfiguration, bool)>((config.Value, true), errors) + : Result.Fail(); } private static string GetNameSpace(StructDeclarationSyntax structSymbol) diff --git a/src/StronglyTypedIds/SourceGenerationHelper.cs b/src/StronglyTypedIds/SourceGenerationHelper.cs index e33515310..1370e50ab 100644 --- a/src/StronglyTypedIds/SourceGenerationHelper.cs +++ b/src/StronglyTypedIds/SourceGenerationHelper.cs @@ -92,19 +92,19 @@ static string CreateId( {"); } - while (parentClass is not null) + while (parentClass is { } parent) { sb .Append(" partial ") - .Append(parentClass.Keyword) + .Append(parent.Keyword) .Append(' ') - .Append(parentClass.Name) + .Append(parent.Name) .Append(' ') - .Append(parentClass.Constraints) + .Append(parent.Constraints) .AppendLine(@" {"); parentsCount++; - parentClass = parentClass.Child; + parentClass = parent.Child; } if (useNewtonsoftJson) @@ -200,15 +200,15 @@ private static void ReplaceInterfaces(StringBuilder sb, bool useIEquatable, bool internal static string CreateSourceName(string nameSpace, ParentClass? parent, string name) { var sb = new StringBuilder(nameSpace).Append('.'); - while (parent != null) + while (parent is { } p) { - var s = parent.Name + var s = p.Name .Replace(" ", "") .Replace(",", "") .Replace("<", "__") .Replace(">", ""); sb.Append(s).Append('.'); - parent = parent.Child; + parent = p.Child; } return sb.Append(name).Append(".g.cs").ToString(); } diff --git a/src/StronglyTypedIds/StronglyTypedIdConfiguration.cs b/src/StronglyTypedIds/StronglyTypedIdConfiguration.cs index 0c4860cd2..0d2406a4b 100644 --- a/src/StronglyTypedIds/StronglyTypedIdConfiguration.cs +++ b/src/StronglyTypedIds/StronglyTypedIdConfiguration.cs @@ -1,7 +1,7 @@ namespace StronglyTypedIds { - internal readonly struct StronglyTypedIdConfiguration + internal readonly record struct StronglyTypedIdConfiguration { public StronglyTypedIdBackingType BackingType { get; } diff --git a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs index 6a299ad78..faaa8c3ff 100644 --- a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs +++ b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Collections.Immutable; using System.Text; using Microsoft.CodeAnalysis; @@ -24,66 +23,70 @@ public void Initialize(IncrementalGeneratorInitializationContext context) i.AddSource("StronglyTypedIdImplementations.g.cs", EmbeddedSources.StronglyTypedIdImplementationsSource); }); - IncrementalValuesProvider structDeclarations = context.SyntaxProvider - .CreateSyntaxProvider( - predicate: static (s, _) => Parser.IsStructTargetForGeneration(s), - transform: static (ctx, _) => Parser.GetStructSemanticTargetForGeneration(ctx)) - .Where(static m => m is not null)!; + IncrementalValuesProvider> structAndDiagnostics = context.SyntaxProvider + .ForAttributeWithMetadataName( + Parser.StronglyTypedIdAttribute, + predicate: (node, _) => node is StructDeclarationSyntax, + transform: Parser.GetStructSemanticTarget) + .Where(static m => m is not null); - IncrementalValuesProvider defaultAttributesDeclarations = context.SyntaxProvider - .CreateSyntaxProvider( - predicate: static (s, _) => Parser.IsAttributeTargetForGeneration(s), - transform: static (ctx, _) => Parser.GetAssemblyAttributeSemanticTargetForGeneration(ctx)) - .Where(static m => m is not null)!; + IncrementalValuesProvider> defaultsAndDiagnostics = context.SyntaxProvider + .ForAttributeWithMetadataName( + Parser.StronglyTypedIdDefaultsAttribute, + predicate: (node, _) => node is CompilationUnitSyntax, + transform: Parser.GetDefaults) + .Where(static m => m is not null); - IncrementalValueProvider<(ImmutableArray, ImmutableArray)> targetsAndDefaultAttributes - = structDeclarations.Collect().Combine(defaultAttributesDeclarations.Collect()); + context.RegisterSourceOutput( + structAndDiagnostics.SelectMany((x, _) => x.Errors), + static (context, info) => context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location))); - IncrementalValueProvider<(Compilation Left, (ImmutableArray, ImmutableArray) Right)> compilationAndValues - = context.CompilationProvider.Combine(targetsAndDefaultAttributes); + context.RegisterSourceOutput( + defaultsAndDiagnostics.SelectMany((x, _) => x.Errors), + static (context, info) => context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location))); - context.RegisterSourceOutput(compilationAndValues, - static (spc, source) => Execute(source.Item1, source.Item2.Item1, source.Item2.Item2, spc)); + IncrementalValuesProvider structs = structAndDiagnostics + .Where(static x => x.Value.valid) + .Select((result, _) => result.Value.info); + + IncrementalValueProvider> allDefaults = defaultsAndDiagnostics + .Where(static x => x.Value.valid) + .Select((result, _) => result.Value.defaults) + .Collect(); + + // we can only use one default attribute + // more than one is an error, but lets do our best + IncrementalValueProvider selectedDefaults = allDefaults + .Select((all, _) => all.IsDefaultOrEmpty ? (StronglyTypedIdConfiguration?)null : all[0]); + + var structsWithDefaults = structs.Combine(selectedDefaults); + + context.RegisterSourceOutput(structsWithDefaults, + static (spc, source) => Execute(source.Left, source.Right, spc)); } static void Execute( - Compilation compilation, - ImmutableArray structs, - ImmutableArray defaults, + StructToGenerate idToGenerate, + StronglyTypedIdConfiguration? defaults, SourceProductionContext context) { - if (structs.IsDefaultOrEmpty) - { - // nothing to do yet - return; - } + var sb = new StringBuilder(); + var values = StronglyTypedIdConfiguration.Combine(idToGenerate.Config, defaults); - List<(string Name, string NameSpace, StronglyTypedIdConfiguration Config, ParentClass? Parent)> idsToGenerate = - Parser.GetTypesToGenerate(compilation, structs, context.ReportDiagnostic, context.CancellationToken); + var result = SourceGenerationHelper.CreateId( + idToGenerate.NameSpace, + idToGenerate.Name, + idToGenerate.Parent, + values.Converters, + values.BackingType, + values.Implementations, + sb); - if (idsToGenerate.Count > 0) - { - StronglyTypedIdConfiguration? globalDefaults = Parser.GetDefaults(defaults, compilation, context.ReportDiagnostic); - StringBuilder sb = new StringBuilder(); - foreach (var idToGenerate in idsToGenerate) - { - sb.Clear(); - var values = StronglyTypedIdConfiguration.Combine(idToGenerate.Config, globalDefaults); - var result = SourceGenerationHelper.CreateId( - idToGenerate.NameSpace, - idToGenerate.Name, - idToGenerate.Parent, - values.Converters, - values.BackingType, - values.Implementations, - sb); - var fileName = SourceGenerationHelper.CreateSourceName( - idToGenerate.NameSpace, - idToGenerate.Parent, - idToGenerate.Name); - context.AddSource(fileName, SourceText.From(result, Encoding.UTF8)); - } - } + var fileName = SourceGenerationHelper.CreateSourceName( + idToGenerate.NameSpace, + idToGenerate.Parent, + idToGenerate.Name); + context.AddSource(fileName, SourceText.From(result, Encoding.UTF8)); } } } \ No newline at end of file diff --git a/src/StronglyTypedIds/StructToGenerate.cs b/src/StronglyTypedIds/StructToGenerate.cs new file mode 100644 index 000000000..16d601704 --- /dev/null +++ b/src/StronglyTypedIds/StructToGenerate.cs @@ -0,0 +1,36 @@ +using System; +using Microsoft.CodeAnalysis.Text; + +namespace StronglyTypedIds; + +internal readonly record struct StructToGenerate +{ + public StructToGenerate(string name, string nameSpace, StronglyTypedIdConfiguration config, ParentClass? parent) + { + Name = name; + NameSpace = nameSpace; + Config = config; + Parent = parent; + } + + public string Name { get; } + public string NameSpace { get; } + public StronglyTypedIdConfiguration Config { get; } + public ParentClass? Parent { get; } +} + +internal sealed record Result + where TValue : IEquatable? +{ + public Result(TValue value, EquatableArray errors) + { + Value = value; + Errors = errors; + } + + public TValue Value { get; } + public EquatableArray Errors { get; } + + public static Result<(TValue, bool)> Fail() + => new((default!, false), EquatableArray.Empty); +} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/EqualityTests.cs b/test/StronglyTypedIds.Tests/EqualityTests.cs new file mode 100644 index 000000000..3270b0a52 --- /dev/null +++ b/test/StronglyTypedIds.Tests/EqualityTests.cs @@ -0,0 +1,136 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using StronglyTypedIds.Diagnostics; +using Xunit; + +namespace StronglyTypedIds.Tests; + +public class EqualityTests +{ + [Fact] + public void ParentClassHasExpectedEqualityBehaviour() + { + var instance1 = GetParentClass(); + var instance2 = GetParentClass(); + + Assert.Equal(instance1, instance2); + Assert.True(instance1.Equals(instance2)); + Assert.True(instance1 == instance2); + + ParentClass GetParentClass() => new("struct", "TestName", "where T : class", null); + } + + [Fact] + public void ParentClassWithParentHasExpectedEqualityBehaviour() + { + var instance1 = GetParentClass(); + var instance2 = GetParentClass(); + + Assert.Equal(instance1, instance2); + Assert.True(instance1.Equals(instance2)); + Assert.True(instance1 == instance2); + + ParentClass GetParentClass() => new("struct", "TestName", "where T : class", new ParentClass("class", "b", "", null)); + } + + [Fact] + public void StronglyTypedIdConfigurationHasExpectedEqualityBehaviour() + { + var id1 = GetId(); + var id2 = GetId(); + Assert.True(id1.Equals(id2)); + Assert.Equal(id1, id2); + } + + private static StronglyTypedIdConfiguration GetId() + { + return new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default); + } + + [Fact] + public void StructToGenerateHasExpectedEqualityBehaviour() + { + var instance1 = GetStruct(); + var instance2 = GetStruct(); + + Assert.Equal(instance1, instance2); + Assert.True(instance1.Equals(instance2)); + Assert.True(instance1 == instance2); + + StructToGenerate GetStruct() => + new( + name: "MyStruct", + nameSpace: "MyNamespace", + config: new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default), + parent: null); + } + + [Fact] + public void StructToGenerateWithParentHasExpectedEqualityBehaviour() + { + var instance1 = GetStruct(); + var instance2 = GetStruct(); + + Assert.Equal(instance1, instance2); + Assert.True(instance1.Equals(instance2)); + Assert.True(instance1 == instance2); + + StructToGenerate GetStruct() + { + return new StructToGenerate( + name: "MyStruct", + nameSpace: "MyNamespace", + config: new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default), + parent: new ParentClass("class", "b", "", null)); + } + } + + [Fact] + public void ResultWithoutDiagnosticHasExpectedEqualityBehaviour() + { + var instance1 = GetResult(); + var instance2 = GetResult(); + + Assert.Equal(instance1, instance2); + Assert.True(instance1.Equals(instance2)); + Assert.True(instance1 == instance2); + + static Result<(StructToGenerate, bool)> GetResult() + { + var instance = new StructToGenerate( + name: "MyStruct", + nameSpace: "MyNamespace", + config: new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default), + parent: new ParentClass("class", "b", "", null)); + + return new Result<(StructToGenerate, bool)>((instance, true), new EquatableArray()); + } + } + + [Fact] + public void ResultWithDiagnosticHasExpectedEqualityBehaviour() + { + var instance1 = GetResult(); + var instance2 = GetResult(); + + Assert.Equal(instance1, instance2); + Assert.True(instance1.Equals(instance2)); + Assert.True(instance1 == instance2); + + static Result<(StructToGenerate, bool)> GetResult() + { + var instance = new StructToGenerate( + name: "MyStruct", + nameSpace: "MyNamespace", + config: new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default), + parent: new ParentClass("class", "b", "", null)); + var diagnostics = new DiagnosticInfo(new DiagnosticDescriptor( + InvalidBackingTypeDiagnostic.Id, InvalidBackingTypeDiagnostic.Title, InvalidBackingTypeDiagnostic.Message, category: Constants.Usage, + defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), + Location.Create("somepath.cs", new TextSpan(), new LinePositionSpan(LinePosition.Zero, LinePosition.Zero))); + + var errors = new EquatableArray(new[] { diagnostics }); + return new Result<(StructToGenerate, bool)>((instance, true), errors); + } + } +} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt new file mode 100644 index 000000000..02e7314d4 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt @@ -0,0 +1,254 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + + readonly partial struct MyId : System.IComparable, System.IEquatable + { + public int Value { get; } + + public MyId(int value) + { + Value = value; + } + + public static readonly MyId Empty = new MyId(0); + + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + } diff --git a/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs b/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs index 383b9a129..f831c5de8 100644 --- a/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs +++ b/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs @@ -159,6 +159,11 @@ public static IEnumerable Parameters() // All individual implementations foreach (var implementation in EnumHelper.AllImplementations(includeDefault: false)) { + if (implementation is StronglyTypedIdImplementations.None) + { + // We've already covered this one in the previous loop + continue; + } yield return new object[] { backingType, StronglyTypedIdConverter.None, implementation }; } } diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs index db399a465..bf9a4912a 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs +++ b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using StronglyTypedIds.Diagnostics; using VerifyXunit; using Xunit; using Xunit.Abstractions; @@ -128,6 +129,23 @@ public partial struct MyId {}"; .UseDirectory("Snapshots"); } + [Fact] + public Task MultipleAssemblyAttributesGeneratesWithDefault() + { + const string input = @"using StronglyTypedIds; +[assembly:StronglyTypedIdDefaults(backingType: StronglyTypedIdBackingType.Int, converters: StronglyTypedIdConverter.None)] +[assembly:StronglyTypedIdDefaults(backingType: StronglyTypedIdBackingType.Long, converters: StronglyTypedIdConverter.None)] + +[StronglyTypedId] +public partial struct MyId {}"; + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + + Assert.Contains(diagnostics, diagnostic => diagnostic.Id == MultipleAssemblyAttributeDiagnostic.Id); + + return Verifier.Verify(output) + .UseDirectory("Snapshots"); + } + [Theory] [MemberData(nameof(GetData))] public Task CanGenerateIdWithNamedParameters(StronglyTypedIdBackingType backingType, StronglyTypedIdConverter? converter) From 47607b0b8e3e42db4fc4b050399dd08363dced55 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Tue, 24 Oct 2023 18:47:00 +0100 Subject: [PATCH 02/47] wip --- .../StronglyTypedIdAttribute.cs | 41 +- .../StronglyTypedIdDefaultsAttribute.cs | 35 +- src/StronglyTypedIds.Attributes/Template.cs | 16 + src/StronglyTypedIds/EmbeddedSources.Guid.cs | 206 +++++ src/StronglyTypedIds/EmbeddedSources.cs | 174 +--- src/StronglyTypedIds/Parser.cs | 282 ++---- .../SourceGenerationHelper.cs | 140 +-- .../StronglyTypedIdConfiguration.cs | 68 -- .../StronglyTypedIdConverterExtensions.cs | 27 - .../StronglyTypedIdGenerator.cs | 108 ++- src/StronglyTypedIds/StronglyTypedIds.csproj | 2 + src/StronglyTypedIds/StructToGenerate.cs | 36 +- .../Templates/AutoGeneratedHeader.cs | 1 + src/StronglyTypedIds/Templates/guid.typedid | 69 ++ src/StronglyTypedIds/Templates/int.typedid | 68 ++ src/StronglyTypedIds/Templates/long.typedid | 70 ++ .../DefaultIdTests.cs | 109 +-- .../Enums.cs | 49 + .../GuidIdTests.cs | 168 ++-- .../IntIdTests.cs | 704 +++++++------- .../LongIdTests.cs | 706 +++++++------- .../MassTransitNewIdTests.cs | 722 +++++++-------- .../NestedIdTests.cs | 10 +- .../NullableStringIdTests.cs | 862 +++++++++--------- .../StringIdTests.cs | 728 +++++++-------- .../StronglyTypedIds.IntegrationTests.csproj | 2 +- .../Types/DefaultId.cs | 41 - .../Types/GuidId.cs | 40 - .../Types/IntId.cs | 37 - .../Types/LongId.cs | 37 - .../Types/NewIdId.cs | 40 - .../Types/NullableStringId.cs | 37 - .../Types/StringId.cs | 37 - test/StronglyTypedIds.Tests/EnumHelper.cs | 66 -- test/StronglyTypedIds.Tests/EqualityTests.cs | 22 +- ...urce=StronglyTypedIdAttribute.verified.txt | 42 +- ...ce=StronglyTypedIdBackingType.verified.txt | 1 + ...urce=StronglyTypedIdConverter.verified.txt | 1 + ...onglyTypedIdDefaultsAttribute.verified.txt | 36 +- ...tronglyTypedIdImplementations.verified.txt | 1 + ...ateDefaultIdInGlobalNamespace.verified.txt | 237 ++--- ...nerateIdInFileScopedNamespace.verified.txt | 237 ++--- ...nerateIdInNamespace.DotNet7_0.received.txt | 524 +++++++++++ ...ests.CanGenerateIdInNamespace.verified.txt | 237 ++--- ...nerateMultipleIdsWithSameName.verified.txt | 237 +---- ...eNestedIdInFileScopeNamespace.verified.txt | 215 +---- ...yNestedIdInFileScopeNamespace.verified.txt | 215 +---- ...eDefaultsUsingGlobalAttribute.verified.txt | 236 ++--- ...ttributesGeneratesWithDefault.verified.txt | 236 ++--- .../SourceGenerationHelperSnapshotTests.cs | 344 +++---- .../StronglyTypedIdConfiguration.cs | 211 ----- .../StronglyTypedIdGeneratorTests.cs | 102 +-- .../StronglyTypedIds.Tests.csproj | 19 + test/StronglyTypedIds.Tests/TestHelpers.cs | 125 ++- 54 files changed, 4179 insertions(+), 4837 deletions(-) create mode 100644 src/StronglyTypedIds.Attributes/Template.cs create mode 100644 src/StronglyTypedIds/EmbeddedSources.Guid.cs delete mode 100644 src/StronglyTypedIds/StronglyTypedIdConfiguration.cs delete mode 100644 src/StronglyTypedIds/StronglyTypedIdConverterExtensions.cs create mode 100644 src/StronglyTypedIds/Templates/guid.typedid create mode 100644 src/StronglyTypedIds/Templates/int.typedid create mode 100644 src/StronglyTypedIds/Templates/long.typedid create mode 100644 test/StronglyTypedIds.IntegrationTests/Enums.cs delete mode 100644 test/StronglyTypedIds.IntegrationTests/Types/DefaultId.cs delete mode 100644 test/StronglyTypedIds.IntegrationTests/Types/GuidId.cs delete mode 100644 test/StronglyTypedIds.IntegrationTests/Types/IntId.cs delete mode 100644 test/StronglyTypedIds.IntegrationTests/Types/LongId.cs delete mode 100644 test/StronglyTypedIds.IntegrationTests/Types/NewIdId.cs delete mode 100644 test/StronglyTypedIds.IntegrationTests/Types/NullableStringId.cs delete mode 100644 test/StronglyTypedIds.IntegrationTests/Types/StringId.cs delete mode 100644 test/StronglyTypedIds.Tests/EnumHelper.cs create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/StronglyTypedIdConfiguration.cs diff --git a/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs b/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs index 68ec67dc9..cfb9b97bc 100644 --- a/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs +++ b/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs @@ -5,7 +5,7 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] public sealed class StronglyTypedIdAttribute : Attribute { @@ -20,6 +20,7 @@ public sealed class StronglyTypedIdAttribute : Attribute /// Interfaces and patterns the strongly typed id should implement /// If not set, uses , which defaults to /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -30,6 +31,34 @@ public StronglyTypedIdAttribute( Implementations = implementations; } + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + /// /// The to use to store the strongly-typed ID value /// @@ -44,5 +73,15 @@ public StronglyTypedIdAttribute( /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } \ No newline at end of file diff --git a/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs b/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs index f7cde494b..f7a7fb6a1 100644 --- a/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs +++ b/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs @@ -3,7 +3,8 @@ namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] @@ -18,6 +19,7 @@ public sealed class StronglyTypedIdDefaultsAttribute : Attribute /// Defaults to and /// Interfaces and patterns the strongly typed id should implement /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdDefaultsAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -28,6 +30,27 @@ public StronglyTypedIdDefaultsAttribute( Implementations = implementations; } + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + /// /// The default to use to store the strongly-typed ID values. /// @@ -42,5 +65,15 @@ public StronglyTypedIdDefaultsAttribute( /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } \ No newline at end of file diff --git a/src/StronglyTypedIds.Attributes/Template.cs b/src/StronglyTypedIds.Attributes/Template.cs new file mode 100644 index 000000000..1a2730191 --- /dev/null +++ b/src/StronglyTypedIds.Attributes/Template.cs @@ -0,0 +1,16 @@ +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + public enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.Guid.cs b/src/StronglyTypedIds/EmbeddedSources.Guid.cs new file mode 100644 index 000000000..6bd1c84e6 --- /dev/null +++ b/src/StronglyTypedIds/EmbeddedSources.Guid.cs @@ -0,0 +1,206 @@ +namespace StronglyTypedIds; + +internal static partial class EmbeddedSources +{ + private const string GuidTemplate = """ + partial struct PLACEHOLDERID: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + #if NET6_0_OR_GREATER + ,global::System.ISpanFormattable + #if NET7_OR_GREATER + global::System.IParsable, global::System.ISpanParsable + #endif + #endif + { + public global::System.Guid Value { get; } + + public PLACEHOLDERID(global::System.Guid value) + { + Value = value; + } + + public static PLACEHOLDERID New() => new PLACEHOLDERID(global::System.Guid.NewGuid()); + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(global::System.Guid.Empty); + + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new PLACEHOLDERID(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + + #if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); + #endif + } + + public static PLACEHOLDERID Parse(string input) + => new(global::System.Guid.Parse(input)); + + #if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + #endif + + /// + public string ToString( + #if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + #endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + + #if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); + #endif + + #if NET6_0_OR_GREATER + #if NET7_0_OR_GREATER + /// + #endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) + #if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); + #else + => new(global::System.Guid.Parse(input)); + #endif + + #if NET7_0_OR_GREATER + /// + #endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { + #if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) + #else + if (global::System.Guid.TryParse(input, out var guid)) + #endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + #if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + #endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + #if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + #endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); + #endif + } + """; +} \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.cs b/src/StronglyTypedIds/EmbeddedSources.cs index e1f229779..8ffcf3200 100644 --- a/src/StronglyTypedIds/EmbeddedSources.cs +++ b/src/StronglyTypedIds/EmbeddedSources.cs @@ -3,154 +3,50 @@ using System.Reflection; using System.Text; -namespace StronglyTypedIds +namespace StronglyTypedIds; + +internal static partial class EmbeddedSources { - internal static class EmbeddedSources + private static readonly Assembly ThisAssembly = typeof(EmbeddedSources).Assembly; + internal static readonly string StronglyTypedIdAttributeSource = LoadTemplateForEmitting("StronglyTypedIdAttribute"); + internal static readonly string StronglyTypedIdDefaultsAttributeSource = LoadTemplateForEmitting("StronglyTypedIdDefaultsAttribute"); + internal static readonly string StronglyTypedIdBackingTypeSource = LoadTemplateForEmitting("StronglyTypedIdBackingType"); + internal static readonly string StronglyTypedIdConverterSource = LoadTemplateForEmitting("StronglyTypedIdConverter"); + internal static readonly string StronglyTypedIdImplementationsSource = LoadTemplateForEmitting("StronglyTypedIdImplementations"); + internal static readonly string TemplateSource = LoadTemplateForEmitting("Template"); + + internal static readonly string AutoGeneratedHeader = LoadEmbeddedResource("StronglyTypedIds.Templates.AutoGeneratedHeader.cs"); + + internal static string GetTemplate(Template template) + => template switch + { + Template.Guid => GuidTemplate, + _ => string.Empty, + }; + + internal static string LoadEmbeddedResource(string resourceName) { - private static readonly Assembly ThisAssembly = typeof(EmbeddedSources).Assembly; - internal static readonly string StronglyTypedIdAttributeSource = LoadTemplateForEmitting("StronglyTypedIdAttribute"); - internal static readonly string StronglyTypedIdDefaultsAttributeSource = LoadTemplateForEmitting("StronglyTypedIdDefaultsAttribute"); - internal static readonly string StronglyTypedIdBackingTypeSource = LoadTemplateForEmitting("StronglyTypedIdBackingType"); - internal static readonly string StronglyTypedIdConverterSource = LoadTemplateForEmitting("StronglyTypedIdConverter"); - internal static readonly string StronglyTypedIdImplementationsSource = LoadTemplateForEmitting("StronglyTypedIdImplementations"); - - private static readonly string AutoGeneratedHeader = LoadEmbeddedResource("StronglyTypedIds.Templates.AutoGeneratedHeader.cs"); - - internal static readonly ResourceCollection GuidResources = new( - AutoGeneratedHeader, - LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_Base.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_NewtonsoftJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_SystemTextJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_TypeConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_EfCoreValueConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_DapperTypeHandler.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_IComparable.cs"), - false - ); - - internal static readonly ResourceCollection IntResources = new( - AutoGeneratedHeader, - LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_Base.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_NewtonsoftJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_SystemTextJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_TypeConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_EfCoreValueConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_DapperTypeHandler.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_IComparable.cs"), - false - ); - - internal static readonly ResourceCollection LongResources = new( - AutoGeneratedHeader, - LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_Base.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_NewtonsoftJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_SystemTextJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_TypeConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_EfCoreValueConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_DapperTypeHandler.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_IComparable.cs"), - false - ); - - internal static readonly ResourceCollection StringResources = new( - AutoGeneratedHeader, - LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_Base.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_NewtonsoftJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_SystemTextJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_TypeConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_EfCoreValueConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_DapperTypeHandler.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_IComparable.cs"), - false - ); - - internal static readonly ResourceCollection NullableStringResources = new( - AutoGeneratedHeader, - LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_Base.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_NewtonsoftJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_SystemTextJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_TypeConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_EfCoreValueConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_DapperTypeHandler.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_IComparable.cs"), - true - ); - - internal static readonly ResourceCollection NewIdResources = new( - AutoGeneratedHeader, - LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_Base.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_NewtonsoftJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_SystemTextJsonConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_TypeConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_EfCoreValueConverter.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_DapperTypeHandler.cs"), - LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_IComparable.cs"), - false - ); - - internal const string TypeConverterAttributeSource = " [System.ComponentModel.TypeConverter(typeof(TESTIDTypeConverter))]"; - internal const string NewtonsoftJsonAttributeSource = " [Newtonsoft.Json.JsonConverter(typeof(TESTIDNewtonsoftJsonConverter))]"; - internal const string SystemTextJsonAttributeSource = " [System.Text.Json.Serialization.JsonConverter(typeof(TESTIDSystemTextJsonConverter))]"; - - internal static string LoadEmbeddedResource(string resourceName) + var resourceStream = ThisAssembly.GetManifestResourceStream(resourceName); + if (resourceStream is null) { - var resourceStream = ThisAssembly.GetManifestResourceStream(resourceName); - if (resourceStream is null) - { - var existingResources = ThisAssembly.GetManifestResourceNames(); - throw new ArgumentException($"Could not find embedded resource {resourceName}. Available names: {string.Join(", ", existingResources)}"); - } - - using var reader = new StreamReader(resourceStream, Encoding.UTF8); - - return reader.ReadToEnd(); + var existingResources = ThisAssembly.GetManifestResourceNames(); + throw new ArgumentException($"Could not find embedded resource {resourceName}. Available names: {string.Join(", ", existingResources)}"); } - public readonly struct ResourceCollection - { - public string Header { get; } - public bool NullableEnable { get; } - public string BaseId { get; } - public string Newtonsoft { get; } - public string SystemTextJson { get; } - public string TypeConverter { get; } - public string EfCoreValueConverter { get; } - public string DapperTypeHandler { get; } - public string Comparable { get; } + using var reader = new StreamReader(resourceStream, Encoding.UTF8); - public ResourceCollection( - string header, - string baseId, - string newtonsoft, - string systemTextJson, - string typeConverter, - string efCoreValueConverter, - string dapperTypeHandler, - string comparable, - bool nullableEnable) - { - BaseId = baseId; - Newtonsoft = newtonsoft; - SystemTextJson = systemTextJson; - TypeConverter = typeConverter; - EfCoreValueConverter = efCoreValueConverter; - DapperTypeHandler = dapperTypeHandler; - Comparable = comparable; - NullableEnable = nullableEnable; - Header = header; - } - } + return reader.ReadToEnd(); + } - internal static string LoadTemplateForEmitting(string resourceName) - { - var resource = LoadEmbeddedResource($"StronglyTypedIds.Templates.Sources.{resourceName}.cs"); - return AutoGeneratedHeader + @"#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + internal static string LoadTemplateForEmitting(string resourceName) + { + var resource = LoadEmbeddedResource($"StronglyTypedIds.Templates.Sources.{resourceName}.cs"); + return AutoGeneratedHeader + @"#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES " + resource - .Replace("public sealed", "internal sealed") - .Replace("public enum", "internal enum") - + @" + .Replace("public sealed", "internal sealed") + .Replace("public enum", "internal enum") + + @" #endif"; - } } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Parser.cs b/src/StronglyTypedIds/Parser.cs index fcc71d0af..6e280ab48 100644 --- a/src/StronglyTypedIds/Parser.cs +++ b/src/StronglyTypedIds/Parser.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; @@ -26,7 +25,8 @@ internal static class Parser var hasMisconfiguredInput = false; List? diagnostics = null; - StronglyTypedIdConfiguration? config = null; + Template? template = null; + string? templateName = null; foreach (AttributeData attribute in structSymbol.GetAttributes()) { @@ -38,99 +38,7 @@ internal static class Parser continue; } - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default; - StronglyTypedIdConverter converter = StronglyTypedIdConverter.Default; - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default; - - if (!attribute.ConstructorArguments.IsEmpty) - { - // make sure we don't have any errors - ImmutableArray args = attribute.ConstructorArguments; - - foreach (TypedConstant arg in args) - { - if (arg.Kind == TypedConstantKind.Error) - { - // have an error, so don't try and do any generation - hasMisconfiguredInput = true; - } - } - - switch (args.Length) - { - case 3: - implementations = (StronglyTypedIdImplementations)args[2].Value!; - goto case 2; - case 2: - converter = (StronglyTypedIdConverter)args[1].Value!; - goto case 1; - case 1: - backingType = (StronglyTypedIdBackingType)args[0].Value!; - break; - } - } - - if (!attribute.NamedArguments.IsEmpty) - { - foreach (KeyValuePair arg in attribute.NamedArguments) - { - TypedConstant typedConstant = arg.Value; - if (typedConstant.Kind == TypedConstantKind.Error) - { - hasMisconfiguredInput = true; - } - else - { - switch (arg.Key) - { - case "backingType": - backingType = (StronglyTypedIdBackingType)typedConstant.Value!; - break; - case "converters": - converter = (StronglyTypedIdConverter)typedConstant.Value!; - break; - case "implementations": - implementations = (StronglyTypedIdImplementations)typedConstant.Value!; - break; - } - } - } - } - - if (hasMisconfiguredInput) - { - // skip further generator execution and let compiler generate the errors - break; - } - - if (!converter.IsValidFlags()) - { - diagnostics ??= new(); - diagnostics.Add(InvalidConverterDiagnostic.CreateInfo(structSyntax)); - } - - if (!Enum.IsDefined(typeof(StronglyTypedIdBackingType), backingType)) - { - diagnostics ??= new(); - diagnostics.Add(InvalidBackingTypeDiagnostic.CreateInfo(structSyntax)); - } - - if (!implementations.IsValidFlags()) - { - diagnostics ??= new(); - diagnostics.Add(InvalidImplementationsDiagnostic.CreateInfo(structSyntax)); - } - - config = new StronglyTypedIdConfiguration(backingType, converter, implementations); - break; - } - - if (config is null || hasMisconfiguredInput) - { - var errors = diagnostics is null - ? EquatableArray.Empty - : new EquatableArray(diagnostics.ToArray()); - return new Result<(StructToGenerate, bool)>((default, false), errors); + hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName); } var hasPartialModifier = false; @@ -149,29 +57,37 @@ internal static class Parser diagnostics.Add(NotPartialDiagnostic.CreateInfo(structSyntax)); } + var errors = diagnostics is null + ? EquatableArray.Empty + : new EquatableArray(diagnostics.ToArray()); + + if (hasMisconfiguredInput) + { + return new Result<(StructToGenerate, bool)>((default, false), errors); + } + string nameSpace = GetNameSpace(structSyntax); ParentClass? parentClass = GetParentClasses(structSyntax); var name = structSymbol.Name; - var errs = diagnostics is null - ? EquatableArray.Empty - : new EquatableArray(diagnostics.ToArray()); - var toGenerate = new StructToGenerate(name: name, nameSpace: nameSpace, config: config.Value, parent: parentClass); - return new Result<(StructToGenerate, bool)>((toGenerate, true), errs); + var toGenerate = new StructToGenerate(name: name, nameSpace: nameSpace, templateName: templateName, parent: parentClass); + return new Result<(StructToGenerate, bool)>((toGenerate, true), errors); } - public static Result<(StronglyTypedIdConfiguration defaults, bool valid)> GetDefaults( + public static Result<(Defaults defaults, bool valid)> GetDefaults( GeneratorAttributeSyntaxContext ctx, CancellationToken ct) { var assemblyAttributes = ctx.TargetSymbol.GetAttributes(); if (assemblyAttributes.IsDefaultOrEmpty) { - return Result.Fail(); + return Result.Fail(); } // We only return the first config that we find - StronglyTypedIdConfiguration? config = null; + string? templateName = null; + Template? template = null; List? diagnostics = null; + bool hasMisconfiguredInput = false; foreach (AttributeData attribute in assemblyAttributes) { @@ -183,7 +99,7 @@ internal static class Parser continue; } - if (config.HasValue) + if (!string.IsNullOrWhiteSpace(templateName) || template.HasValue) { if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } s) { @@ -194,114 +110,96 @@ internal static class Parser continue; } - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default; - StronglyTypedIdConverter converter = StronglyTypedIdConverter.Default; - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default; - bool hasMisconfiguredInput = false; - - if (!attribute.ConstructorArguments.IsEmpty) - { - // make sure we don't have any errors - ImmutableArray args = attribute.ConstructorArguments; - - foreach (TypedConstant arg in args) - { - if (arg.Kind == TypedConstantKind.Error) - { - // have an error, so don't try and do any generation - hasMisconfiguredInput = true; - } - } - - switch (args.Length) - { - case 3: - implementations = (StronglyTypedIdImplementations)args[2].Value!; - goto case 2; - case 2: - converter = (StronglyTypedIdConverter)args[1].Value!; - goto case 1; - case 1: - backingType = (StronglyTypedIdBackingType)args[0].Value!; - break; - } - } - - if (!attribute.NamedArguments.IsEmpty) - { - foreach (KeyValuePair arg in attribute.NamedArguments) - { - TypedConstant typedConstant = arg.Value; - if (typedConstant.Kind == TypedConstantKind.Error) - { - hasMisconfiguredInput = true; - } - else - { - switch (arg.Key) - { - case "backingType": - backingType = (StronglyTypedIdBackingType)typedConstant.Value!; - break; - case "converters": - converter = (StronglyTypedIdConverter)typedConstant.Value!; - break; - case "implementations": - implementations = (StronglyTypedIdImplementations)typedConstant.Value!; - break; - } - } - } - } - + hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName); + if (hasMisconfiguredInput) { // skip further generator execution and let compiler generate the errors break; } - - SyntaxNode? syntax = null; + } + + var errors = diagnostics is null + ? EquatableArray.Empty + : new EquatableArray(diagnostics.ToArray()); + + if (hasMisconfiguredInput) + { + return new Result<(Defaults, bool)>((default, false), errors); + } + + var defaults = template.HasValue + ? new Defaults(template.Value) + : new Defaults(templateName!); + + return new Result<(Defaults, bool)>((defaults, true), errors); + } + + private static bool GetConstructorValues(AttributeData attribute, out Template? template, out string? templateName) + { + var hasMisconfiguredInput = false; + template = null; + templateName = null; + + if (!attribute.ConstructorArguments.IsEmpty) + { + // make sure we don't have any errors + ImmutableArray args = attribute.ConstructorArguments; - if (!converter.IsValidFlags()) + foreach (TypedConstant arg in args) { - syntax = attribute.ApplicationSyntaxReference?.GetSyntax(); - if (syntax is not null) + if (arg.Kind == TypedConstantKind.Error) { - diagnostics ??= new(); - diagnostics.Add(InvalidConverterDiagnostic.CreateInfo(syntax)); + // have an error, so don't try and do any generation + hasMisconfiguredInput = true; } } - - if (!Enum.IsDefined(typeof(StronglyTypedIdBackingType), backingType)) + + if (args[0].Value is int enumValue) + { + template = (Template) enumValue; + } + else { - syntax ??= attribute.ApplicationSyntaxReference?.GetSyntax(); - if (syntax is not null) + templateName = args[0].Value as string; + if (string.IsNullOrWhiteSpace(templateName)) { - diagnostics ??= new(); - diagnostics.Add(InvalidBackingTypeDiagnostic.CreateInfo(syntax)); + // TODO: add diagnostic + hasMisconfiguredInput = true; } } - - if (!implementations.IsValidFlags()) + } + + if (!attribute.NamedArguments.IsEmpty) + { + foreach (KeyValuePair arg in attribute.NamedArguments) { - syntax ??= attribute.ApplicationSyntaxReference?.GetSyntax(); - if (syntax is not null) + TypedConstant typedConstant = arg.Value; + if (typedConstant.Kind == TypedConstantKind.Error) { - diagnostics ??= new(); - diagnostics.Add(InvalidImplementationsDiagnostic.CreateInfo(syntax)); + hasMisconfiguredInput = true; + break; } - } - config = new StronglyTypedIdConfiguration(backingType, converter, implementations); - } + if (typedConstant.Value is int enumValue) + { + template = (Template) enumValue; + } + else + { + templateName = typedConstant.Value as string; + if (string.IsNullOrWhiteSpace(templateName)) + { + // TODO: add diagnostic + hasMisconfiguredInput = true; + } + } - var errors = diagnostics is null - ? EquatableArray.Empty - : new EquatableArray(diagnostics.ToArray()); + break; + } + } - return config.HasValue - ? new Result<(StronglyTypedIdConfiguration, bool)>((config.Value, true), errors) - : Result.Fail(); + return hasMisconfiguredInput; } private static string GetNameSpace(StructDeclarationSyntax structSymbol) diff --git a/src/StronglyTypedIds/SourceGenerationHelper.cs b/src/StronglyTypedIds/SourceGenerationHelper.cs index 1370e50ab..264fdb0e6 100644 --- a/src/StronglyTypedIds/SourceGenerationHelper.cs +++ b/src/StronglyTypedIds/SourceGenerationHelper.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Text; namespace StronglyTypedIds @@ -10,41 +9,14 @@ public static string CreateId( string idNamespace, string idName, ParentClass? parentClass, - StronglyTypedIdConverter converters, - StronglyTypedIdBackingType backingType, - StronglyTypedIdImplementations implementations) - => CreateId(idNamespace, idName, parentClass, converters, backingType, implementations, null); + string template) + => CreateId(idNamespace, idName, parentClass, template, null); public static string CreateId( string idNamespace, string idName, ParentClass? parentClass, - StronglyTypedIdConverter converters, - StronglyTypedIdBackingType backingType, - StronglyTypedIdImplementations implementations, - StringBuilder? sb) - { - var resources = backingType switch - { - StronglyTypedIdBackingType.Guid => EmbeddedSources.GuidResources, - StronglyTypedIdBackingType.Int => EmbeddedSources.IntResources, - StronglyTypedIdBackingType.Long => EmbeddedSources.LongResources, - StronglyTypedIdBackingType.String => EmbeddedSources.StringResources, - StronglyTypedIdBackingType.NullableString => EmbeddedSources.NullableStringResources, - StronglyTypedIdBackingType.MassTransitNewId => EmbeddedSources.NewIdResources, - _ => throw new ArgumentException("Unknown backing type: " + backingType, nameof(backingType)), - }; - - return CreateId(idNamespace, idName, parentClass, converters, implementations, resources, sb); - } - - static string CreateId( - string idNamespace, - string idName, - ParentClass? parentClass, - StronglyTypedIdConverter converters, - StronglyTypedIdImplementations implementations, - EmbeddedSources.ResourceCollection resources, + string template, StringBuilder? sb) { if (string.IsNullOrEmpty(idName)) @@ -52,36 +24,12 @@ static string CreateId( throw new ArgumentException("Value cannot be null or empty.", nameof(idName)); } - if (converters == StronglyTypedIdConverter.Default) - { - throw new ArgumentException("Cannot use default converter - must provide concrete values or None", nameof(converters)); - } - - if (implementations == StronglyTypedIdImplementations.Default) - { - throw new ArgumentException("Cannot use default implementations - must provide concrete values or None", nameof(implementations)); - } - var hasNamespace = !string.IsNullOrEmpty(idNamespace); - var useTypeConverter = converters.IsSet(StronglyTypedIdConverter.TypeConverter); - var useNewtonsoftJson = converters.IsSet(StronglyTypedIdConverter.NewtonsoftJson); - var useSystemTextJson = converters.IsSet(StronglyTypedIdConverter.SystemTextJson); - var useEfCoreValueConverter = converters.IsSet(StronglyTypedIdConverter.EfCoreValueConverter); - var useDapperTypeHandler = converters.IsSet(StronglyTypedIdConverter.DapperTypeHandler); - - var useIEquatable = implementations.IsSet(StronglyTypedIdImplementations.IEquatable); - var useIComparable = implementations.IsSet(StronglyTypedIdImplementations.IComparable); - var parentsCount = 0; sb ??= new StringBuilder(); - sb.Append(resources.Header); - - if (resources.NullableEnable) - { - sb.AppendLine("#nullable enable"); - } + sb.Append(EmbeddedSources.AutoGeneratedHeader); if (hasNamespace) { @@ -106,59 +54,13 @@ static string CreateId( parentsCount++; parentClass = parent.Child; } + + // TODO: can't add this if it's a generic class + sb.AppendLine(" [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))]"); - if (useNewtonsoftJson) - { - sb.AppendLine(EmbeddedSources.NewtonsoftJsonAttributeSource); - } - - if (useSystemTextJson) - { - sb.AppendLine(EmbeddedSources.SystemTextJsonAttributeSource); - } - - if (useTypeConverter) - { - sb.AppendLine(EmbeddedSources.TypeConverterAttributeSource); - } - - sb.Append(resources.BaseId); - ReplaceInterfaces(sb, useIEquatable, useIComparable); - - // IEquatable is already implemented whether or not the interface is implemented - - if (useIComparable) - { - sb.AppendLine(resources.Comparable); - } - - if (useEfCoreValueConverter) - { - sb.AppendLine(resources.EfCoreValueConverter); - } - - if (useDapperTypeHandler) - { - sb.AppendLine(resources.DapperTypeHandler); - } - - if (useTypeConverter) - { - sb.AppendLine(resources.TypeConverter); - } - - if (useNewtonsoftJson) - { - sb.AppendLine(resources.Newtonsoft); - } + sb.AppendLine(template); - if (useSystemTextJson) - { - sb.AppendLine(resources.SystemTextJson); - } - - sb.Replace("TESTID", idName); - sb.AppendLine(@" }"); + sb.Replace("PLACEHOLDERID", idName); for (int i = 0; i < parentsCount; i++) { @@ -173,30 +75,6 @@ static string CreateId( return sb.ToString(); } - private static void ReplaceInterfaces(StringBuilder sb, bool useIEquatable, bool useIComparable) - { - var interfaces = new List(); - - if (useIComparable) - { - interfaces.Add("System.IComparable"); - } - - if (useIEquatable) - { - interfaces.Add("System.IEquatable"); - } - - if (interfaces.Count > 0) - { - sb.Replace("INTERFACES", string.Join(", ", interfaces)); - } - else - { - sb.Replace(": INTERFACES", string.Empty); - } - } - internal static string CreateSourceName(string nameSpace, ParentClass? parent, string name) { var sb = new StringBuilder(nameSpace).Append('.'); diff --git a/src/StronglyTypedIds/StronglyTypedIdConfiguration.cs b/src/StronglyTypedIds/StronglyTypedIdConfiguration.cs deleted file mode 100644 index 0d2406a4b..000000000 --- a/src/StronglyTypedIds/StronglyTypedIdConfiguration.cs +++ /dev/null @@ -1,68 +0,0 @@ - -namespace StronglyTypedIds -{ - internal readonly record struct StronglyTypedIdConfiguration - { - public StronglyTypedIdBackingType BackingType { get; } - - public StronglyTypedIdConverter Converters { get; } - - public StronglyTypedIdImplementations Implementations { get; } - - public StronglyTypedIdConfiguration( - StronglyTypedIdBackingType backingType, - StronglyTypedIdConverter converters, - StronglyTypedIdImplementations implementations) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Gets the default values for when a default attribute is not used. - /// Should be kept in sync with the default values referenced in - /// and , but should always be "definite" values (not "Default") - /// - public static readonly StronglyTypedIdConfiguration Defaults = new( - backingType: StronglyTypedIdBackingType.Guid, - converters: StronglyTypedIdConverter.TypeConverter | StronglyTypedIdConverter.NewtonsoftJson, - implementations: StronglyTypedIdImplementations.IEquatable | StronglyTypedIdImplementations.IComparable); - - /// - /// Combines multiple values associated - /// with a given , returning definite values. - /// - /// - public static StronglyTypedIdConfiguration Combine( - StronglyTypedIdConfiguration attributeValues, - StronglyTypedIdConfiguration? globalValues) - { - var backingType = (attributeValues.BackingType, globalValues?.BackingType) switch - { - (StronglyTypedIdBackingType.Default, null) => Defaults.BackingType, - (StronglyTypedIdBackingType.Default, StronglyTypedIdBackingType.Default) => Defaults.BackingType, - (StronglyTypedIdBackingType.Default, var globalDefault) => globalDefault.Value, - (var specificValue, _) => specificValue - }; - - var converter = (attributeValues.Converters, globalValues?.Converters) switch - { - (StronglyTypedIdConverter.Default, null) => Defaults.Converters, - (StronglyTypedIdConverter.Default, StronglyTypedIdConverter.Default) => Defaults.Converters, - (StronglyTypedIdConverter.Default, var globalDefault) => globalDefault.Value, - (var specificValue, _) => specificValue - }; - - var implementations = (attributeValues.Implementations, globalValues?.Implementations) switch - { - (StronglyTypedIdImplementations.Default, null) => Defaults.Implementations, - (StronglyTypedIdImplementations.Default, StronglyTypedIdImplementations.Default) => Defaults.Implementations, - (StronglyTypedIdImplementations.Default, var globalDefault) => globalDefault.Value, - (var specificValue, _) => specificValue - }; - - return new StronglyTypedIdConfiguration(backingType, converter, implementations); - } - } -} \ No newline at end of file diff --git a/src/StronglyTypedIds/StronglyTypedIdConverterExtensions.cs b/src/StronglyTypedIds/StronglyTypedIdConverterExtensions.cs deleted file mode 100644 index 63d4174b2..000000000 --- a/src/StronglyTypedIds/StronglyTypedIdConverterExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Linq; - -namespace StronglyTypedIds -{ - internal static class StronglyTypedIdConverterExtensions - { - private static readonly int _maxConverterId = Enum.GetValues(typeof(StronglyTypedIdConverter)).Cast().Max() * 2; - private static readonly int _maxImplementationsId = Enum.GetValues(typeof(StronglyTypedIdImplementations)).Cast().Max() * 2; - - public static bool IsSet(this StronglyTypedIdConverter value, StronglyTypedIdConverter flag) - => (value & flag) == flag; - - public static bool IsValidFlags(this StronglyTypedIdConverter value) - { - return (int)value >= 0 && (int)value < _maxConverterId; - } - - public static bool IsSet(this StronglyTypedIdImplementations value, StronglyTypedIdImplementations flag) - => (value & flag) == flag; - - public static bool IsValidFlags(this StronglyTypedIdImplementations value) - { - return (int)value >= 0 && (int)value < _maxImplementationsId; - } - } -} \ No newline at end of file diff --git a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs index faaa8c3ff..fc7ec707b 100644 --- a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs +++ b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs @@ -1,4 +1,7 @@ +using System; +using System.Collections.Generic; using System.Collections.Immutable; +using System.IO; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -10,6 +13,8 @@ namespace StronglyTypedIds [Generator] public class StronglyTypedIdGenerator : IIncrementalGenerator { + const string TemplateSuffix = ".typedid"; + /// public void Initialize(IncrementalGeneratorInitializationContext context) { @@ -21,8 +26,23 @@ public void Initialize(IncrementalGeneratorInitializationContext context) i.AddSource("StronglyTypedIdBackingType.g.cs", EmbeddedSources.StronglyTypedIdBackingTypeSource); i.AddSource("StronglyTypedIdConverter.g.cs", EmbeddedSources.StronglyTypedIdConverterSource); i.AddSource("StronglyTypedIdImplementations.g.cs", EmbeddedSources.StronglyTypedIdImplementationsSource); + i.AddSource("Template.g.cs", EmbeddedSources.TemplateSource); }); + IncrementalValuesProvider<(string Path, string Name, string? Content)> allTemplates = context.AdditionalTextsProvider + .Where(template => Path.GetExtension(template.Path).Equals(TemplateSuffix, StringComparison.OrdinalIgnoreCase)) + .Select((template, ct) => ( + Path: template.Path, + Name: Path.GetFileNameWithoutExtension(template.Path), + Content: template.GetText(ct)?.ToString())); + + var templatesWithErrors = allTemplates + .Where(template => string.IsNullOrWhiteSpace(template.Name) || template.Content is null); + + var templates = allTemplates + .Where(template => !string.IsNullOrWhiteSpace(template.Name) && template.Content is not null) + .Collect(); + IncrementalValuesProvider> structAndDiagnostics = context.SyntaxProvider .ForAttributeWithMetadataName( Parser.StronglyTypedIdAttribute, @@ -30,7 +50,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) transform: Parser.GetStructSemanticTarget) .Where(static m => m is not null); - IncrementalValuesProvider> defaultsAndDiagnostics = context.SyntaxProvider + IncrementalValuesProvider> defaultsAndDiagnostics = context.SyntaxProvider .ForAttributeWithMetadataName( Parser.StronglyTypedIdDefaultsAttribute, predicate: (node, _) => node is CompilationUnitSyntax, @@ -45,41 +65,97 @@ public void Initialize(IncrementalGeneratorInitializationContext context) defaultsAndDiagnostics.SelectMany((x, _) => x.Errors), static (context, info) => context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location))); + // context.RegisterSourceOutput( + // templatesWithErrors, + // static (context, info) => context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location))); + IncrementalValuesProvider structs = structAndDiagnostics .Where(static x => x.Value.valid) .Select((result, _) => result.Value.info); - IncrementalValueProvider> allDefaults = defaultsAndDiagnostics + + IncrementalValueProvider defaultTemplateContent = defaultsAndDiagnostics .Where(static x => x.Value.valid) .Select((result, _) => result.Value.defaults) - .Collect(); + .Collect() + .Combine(templates) + .Select((all, _) => + { + // we can only use one default attribute + // more than one is an error, but lets do our best + var defaults = all.Left.IsDefaultOrEmpty ? (Defaults?) null : all.Left[0]; + if (defaults?.Template is { } templateId) + { + return EmbeddedSources.GetTemplate(templateId); + } + + var defaultsTemplateName = defaults?.TemplateName; + if(!string.IsNullOrEmpty(defaultsTemplateName)) + { + foreach (var templateDetails in all.Right) + { + if (string.Equals(templateDetails.Name, defaultsTemplateName, StringComparison.Ordinal)) + { + // This _could_ be empty, but we use it anyway (and add a warning in the template) + return templateDetails.Content; + } + } - // we can only use one default attribute - // more than one is an error, but lets do our best - IncrementalValueProvider selectedDefaults = allDefaults - .Select((all, _) => all.IsDefaultOrEmpty ? (StronglyTypedIdConfiguration?)null : all[0]); + // TODO: Add diagnostic that couldn't find a template with the right name + // TODO: Add a warning in a comment to the code too? + // context.ReportDiagnostic(); + } - var structsWithDefaults = structs.Combine(selectedDefaults); + // no default + return null; + }); - context.RegisterSourceOutput(structsWithDefaults, - static (spc, source) => Execute(source.Left, source.Right, spc)); + var structsWithDefaultsAndTemplates = structs + .Combine(templates) + .Combine(defaultTemplateContent); + + context.RegisterSourceOutput(structsWithDefaultsAndTemplates, + static (spc, source) => Execute(source.Left.Left, source.Left.Right, source.Right, spc)); } - static void Execute( + private static void Execute( StructToGenerate idToGenerate, - StronglyTypedIdConfiguration? defaults, + ImmutableArray<(string Path, string Name, string? Content)> templates, + string? defaultTemplateContent, SourceProductionContext context) { var sb = new StringBuilder(); - var values = StronglyTypedIdConfiguration.Combine(idToGenerate.Config, defaults); + + string? template = null!; + if (idToGenerate.Template is { } templateId) + { + template = EmbeddedSources.GetTemplate(templateId); + } + else if(!string.IsNullOrEmpty(idToGenerate.TemplateName)) + { + foreach (var templateDetails in templates) + { + if (string.Equals(templateDetails.Name, idToGenerate.TemplateName, StringComparison.Ordinal)) + { + template = templateDetails.Content; + break; + } + } + + // TODO: Add diagnostic that couldn't find a template with the right name + // context.ReportDiagnostic(); + } + + if (string.IsNullOrEmpty(template)) + { + template = defaultTemplateContent ?? EmbeddedSources.GetTemplate(Template.Guid); + } var result = SourceGenerationHelper.CreateId( idToGenerate.NameSpace, idToGenerate.Name, idToGenerate.Parent, - values.Converters, - values.BackingType, - values.Implementations, + template!, sb); var fileName = SourceGenerationHelper.CreateSourceName( diff --git a/src/StronglyTypedIds/StronglyTypedIds.csproj b/src/StronglyTypedIds/StronglyTypedIds.csproj index 64f63c39f..8e9d26610 100644 --- a/src/StronglyTypedIds/StronglyTypedIds.csproj +++ b/src/StronglyTypedIds/StronglyTypedIds.csproj @@ -6,6 +6,7 @@ enable StronglyTypedId A source generator for creating strongly-typed IDs by decorating with a [StronglyTypedId] attribute + latest @@ -18,6 +19,7 @@ + diff --git a/src/StronglyTypedIds/StructToGenerate.cs b/src/StronglyTypedIds/StructToGenerate.cs index 16d601704..f77083d20 100644 --- a/src/StronglyTypedIds/StructToGenerate.cs +++ b/src/StronglyTypedIds/StructToGenerate.cs @@ -5,17 +5,28 @@ namespace StronglyTypedIds; internal readonly record struct StructToGenerate { - public StructToGenerate(string name, string nameSpace, StronglyTypedIdConfiguration config, ParentClass? parent) + public StructToGenerate(string name, string nameSpace, string? templateName, ParentClass? parent) { Name = name; NameSpace = nameSpace; - Config = config; + TemplateName = templateName; + Template = null; + Parent = parent; + } + + public StructToGenerate(string name, string nameSpace, Template template, ParentClass? parent) + { + Name = name; + NameSpace = nameSpace; + TemplateName = null; + Template = template; Parent = parent; } public string Name { get; } public string NameSpace { get; } - public StronglyTypedIdConfiguration Config { get; } + public string? TemplateName { get; } + public Template? Template { get; } public ParentClass? Parent { get; } } @@ -33,4 +44,23 @@ public Result(TValue value, EquatableArray errors) public static Result<(TValue, bool)> Fail() => new((default!, false), EquatableArray.Empty); +} + + +internal readonly record struct Defaults +{ + public Defaults(string templateName) + { + TemplateName = templateName; + Template = null; + } + + public Defaults(Template template) + { + TemplateName = null; + Template = template; + } + + public string? TemplateName { get; } + public Template? Template { get; } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/AutoGeneratedHeader.cs b/src/StronglyTypedIds/Templates/AutoGeneratedHeader.cs index 76952553c..b782f6438 100644 --- a/src/StronglyTypedIds/Templates/AutoGeneratedHeader.cs +++ b/src/StronglyTypedIds/Templates/AutoGeneratedHeader.cs @@ -9,3 +9,4 @@ #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable diff --git a/src/StronglyTypedIds/Templates/guid.typedid b/src/StronglyTypedIds/Templates/guid.typedid new file mode 100644 index 000000000..f9156173c --- /dev/null +++ b/src/StronglyTypedIds/Templates/guid.typedid @@ -0,0 +1,69 @@ + [System.ComponentModel.TypeConverter(typeof(TESTIDTypeConverter))] + readonly partial struct TESTID : System.IComparable, System.IEquatable + { + public System.Guid Value { get; } + + public TESTID(System.Guid value) + { + Value = value; + } + + public static TESTID New() => new TESTID(System.Guid.NewGuid()); + public static readonly TESTID Empty = new TESTID(System.Guid.Empty); + + public bool Equals(TESTID other) => this.Value.Equals(other.Value); + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is TESTID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); + public static bool operator !=(TESTID a, TESTID b) => !(a == b); + + public int CompareTo(TESTID other) => Value.CompareTo(other.Value); + + class TESTIDTypeConverter : System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + return value switch + { + System.Guid guidValue => new TESTID(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new TESTID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + { + if (value is TESTID idValue) + { + if (destinationType == typeof(System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/int.typedid b/src/StronglyTypedIds/Templates/int.typedid new file mode 100644 index 000000000..569d36875 --- /dev/null +++ b/src/StronglyTypedIds/Templates/int.typedid @@ -0,0 +1,68 @@ + [System.ComponentModel.TypeConverter(typeof(TESTIDTypeConverter))] + readonly partial struct TESTID : System.IComparable, System.IEquatable + { + public int Value { get; } + + public TESTID(int value) + { + Value = value; + } + + public static readonly TESTID Empty = new TESTID(0); + + public bool Equals(TESTID other) => this.Value.Equals(other.Value); + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is TESTID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); + public static bool operator !=(TESTID a, TESTID b) => !(a == b); + + public int CompareTo(TESTID other) => Value.CompareTo(other.Value); + + class TESTIDTypeConverter : System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + return value switch + { + int intValue => new TESTID(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new TESTID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + { + if (value is TESTID idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/long.typedid b/src/StronglyTypedIds/Templates/long.typedid new file mode 100644 index 000000000..299ae0361 --- /dev/null +++ b/src/StronglyTypedIds/Templates/long.typedid @@ -0,0 +1,70 @@ + [System.ComponentModel.TypeConverter(typeof(TESTIDTypeConverter))] + readonly partial struct TESTID : System.IComparable, System.IEquatable + { + public int Value { get; } + + public TESTID(int value) + { + Value = value; + } + + public static readonly TESTID Empty = new TESTID(0); + + public bool Equals(TESTID other) => this.Value.Equals(other.Value); + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is TESTID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); + public static bool operator !=(TESTID a, TESTID b) => !(a == b); + + public int CompareTo(TESTID other) => Value.CompareTo(other.Value); + + class TESTIDTypeConverter : System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(long) || sourceType == typeof(int) || sourceType == typeof(short) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + return value switch + { + long longValue => new TESTID(longValue), + int intValue => new TESTID(intValue), + short shortValue => new TESTID(shortValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new TESTID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + { + if (value is TESTID idValue) + { + if (destinationType == typeof(long)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/DefaultIdTests.cs b/test/StronglyTypedIds.IntegrationTests/DefaultIdTests.cs index b374909c3..83d4ca184 100644 --- a/test/StronglyTypedIds.IntegrationTests/DefaultIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/DefaultIdTests.cs @@ -85,120 +85,17 @@ public void WhenNoTypeConverter_SerializesWithValueProperty() Assert.Equal(expected, systemText); } - [Fact] - public void WhenEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - using (var context = new TestDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity { Id = EfCoreDefaultId.New() }); - context.SaveChanges(); - } - using (var context = new TestDbContext(options)) - { - var all = context.Entities.ToList(); - Assert.Single(all); - } - } - [Theory] [InlineData("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")] public void TypeConverter_CanConvertToAndFrom(string value) { - var converter = TypeDescriptor.GetConverter(typeof(NoJsonDefaultId)); + var converter = TypeDescriptor.GetConverter(typeof(DefaultId1)); var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new NoJsonDefaultId(Guid.Parse(value)), id); + Assert.IsType(id); + Assert.Equal(new DefaultId1(Guid.Parse(value)), id); var reconverted = converter.ConvertTo(id, value.GetType()); Assert.Equal(value, reconverted); } - -#if NET6_0_OR_GREATER - [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - using (var context = new ConventionsDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity { Id = EfCoreDefaultId.New() }); - context.SaveChanges(); - } - using (var context = new ConventionsDbContext(options)) - { - var all = context.Entities.ToList(); - Assert.Single(all); - } - } - - public class ConventionsDbContext : DbContext - { - public DbSet Entities { get; set; } - - public ConventionsDbContext(DbContextOptions options) : base(options) - { - } - - protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) - { - configurationBuilder - .Properties() - .HaveConversion(); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .ValueGeneratedNever(); - }); - } - } -#endif - - public class TestDbContext : DbContext - { - public DbSet Entities { get; set; } - - public TestDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .HasConversion(new EfCoreDefaultId.EfCoreValueConverter()) - .ValueGeneratedNever(); - }); - } - } - - public class TestEntity - { - public EfCoreDefaultId Id { get; set; } - } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs new file mode 100644 index 000000000..f8fe47426 --- /dev/null +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -0,0 +1,49 @@ +using System.Text.Json; +using StronglyTypedIds; +#nullable enable +namespace StronglyTypedIds.IntegrationTests.Types +{ + [StronglyTypedId] + partial struct DefaultId1 { } + + [StronglyTypedId] + public partial struct DefaultId2 { } + + [StronglyTypedId(Template.Guid)] + partial struct GuidId1 { } + + [StronglyTypedId(Template.Guid)] + public partial struct GuidId2 { } + + // [StronglyTypedId(Template.Int)] + // partial struct IntId { } + // + // [StronglyTypedId(Template.Long)] + // partial struct LongId { } + // + // [StronglyTypedId("newid")] + // partial struct NewIdId1 { } + // + // [StronglyTypedId("newid")] + // public partial struct NewIdId2 { } + // + // [StronglyTypedId(Template.NullableString)] + // partial struct NullableStringId { } + // + // [StronglyTypedId(Template.String)] + // partial struct StringId { } + + // public partial class SomeType where T : new() + // { + // public partial record NestedType + // { + // public partial struct MoreNesting + // { + // [StronglyTypedId] + // public partial struct VeryNestedIds + // { + // } + // } + // } + // } +} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs index 2905f70e6..bebbd570b 100644 --- a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs @@ -271,89 +271,89 @@ public void ImplementsInterfaces() Assert.False(GuidId1.Empty is IEquatable); #pragma warning restore 184 } - -#if NET6_0_OR_GREATER - [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - using (var context = new ConventionsDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity { Id = EfCoreGuidId.New() }); - context.SaveChanges(); - } - using (var context = new ConventionsDbContext(options)) - { - var all = context.Entities.ToList(); - Assert.Single(all); - } - } - - public class ConventionsDbContext : DbContext - { - public DbSet Entities { get; set; } - - public ConventionsDbContext(DbContextOptions options) : base(options) - { - } - - protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) - { - configurationBuilder - .Properties() - .HaveConversion(); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .ValueGeneratedNever(); - }); - } - } -#endif - - public class TestDbContext : DbContext - { - public DbSet Entities { get; set; } - - public TestDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .HasConversion(new EfCoreGuidId.EfCoreValueConverter()) - .ValueGeneratedNever(); - }); - } - } - - public class TestEntity - { - public EfCoreGuidId Id { get; set; } - } - - public class EntityWithNullableId - { - public NewtonsoftJsonGuidId? Id { get; set; } - } +// +// #if NET6_0_OR_GREATER +// [Fact] +// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() +// { +// var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// using (var context = new ConventionsDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add( +// new TestEntity { Id = EfCoreGuidId.New() }); +// context.SaveChanges(); +// } +// using (var context = new ConventionsDbContext(options)) +// { +// var all = context.Entities.ToList(); +// Assert.Single(all); +// } +// } +// +// public class ConventionsDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public ConventionsDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) +// { +// configurationBuilder +// .Properties() +// .HaveConversion(); +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .ValueGeneratedNever(); +// }); +// } +// } +// #endif +// +// public class TestDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public TestDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .HasConversion(new EfCoreGuidId.EfCoreValueConverter()) +// .ValueGeneratedNever(); +// }); +// } +// } +// +// public class TestEntity +// { +// public EfCoreGuidId Id { get; set; } +// } +// +// public class EntityWithNullableId +// { +// public NewtonsoftJsonGuidId? Id { get; set; } +// } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs index e2c48be64..24bed3950 100644 --- a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs @@ -1,352 +1,352 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Threading.Tasks; -using Dapper; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using StronglyTypedIds.IntegrationTests.Types; -using Xunit; -using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; - -namespace StronglyTypedIds.IntegrationTests -{ - public class IntIdTests - { - [Fact] - public void SameValuesAreEqual() - { - var id = 123; - var foo1 = new IntId(id); - var foo2 = new IntId(id); - - Assert.Equal(foo1, foo2); - } - - [Fact] - public void EmptyValueIsEmpty() - { - Assert.Equal(0, IntId.Empty.Value); - } - - - [Fact] - public void DifferentValuesAreUnequal() - { - var foo1 = new IntId(1); - var foo2 = new IntId(2); - - Assert.NotEqual(foo1, foo2); - } - - [Fact] - public void OverloadsWorkCorrectly() - { - var id = 12; - var same1 = new IntId(id); - var same2 = new IntId(id); - var different = new IntId(3); - - Assert.True(same1 == same2); - Assert.False(same1 == different); - Assert.False(same1 != same2); - Assert.True(same1 != different); - } - - [Fact] - public void DifferentTypesAreUnequal() - { - var bar = GuidId2.New(); - var foo = new IntId(23); - - //Assert.NotEqual(bar, foo); // does not compile - Assert.NotEqual((object)bar, (object)foo); - } - - [Fact] - public void CanSerializeToInt_WithNewtonsoftJsonProvider() - { - var foo = new NewtonsoftJsonIntId(123); - - var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedInt = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - Assert.Equal(serializedFoo, serializedInt); - } - - [Fact] - public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() - { - var entity = new EntityWithNullableId { Id = null }; - - var json = NewtonsoftJsonSerializer.SerializeObject(entity); - var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); - - Assert.NotNull(deserialize); - Assert.Null(deserialize.Id); - } - - [Fact] - public void CanSerializeToInt_WithSystemTextJsonProvider() - { - var foo = new SystemTextJsonIntId(123); - - var serializedFoo = SystemTextJsonSerializer.Serialize(foo); - var serializedInt = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo, serializedInt); - } - - [Fact] - public void CanDeserializeFromInt_WithNewtonsoftJsonProvider() - { - var value = 123; - var foo = new NewtonsoftJsonIntId(value); - var serializedInt = NewtonsoftJsonSerializer.SerializeObject(value); - - var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedInt); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanDeserializeFromInt_WithSystemTextJsonProvider() - { - var value = 123; - var foo = new SystemTextJsonIntId(value); - var serializedInt = SystemTextJsonSerializer.Serialize(value); - - var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedInt); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanSerializeToInt_WithBothJsonConverters() - { - var foo = new BothJsonIntId(123); - - var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedInt1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); - var serializedInt2 = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo1, serializedInt1); - Assert.Equal(serializedFoo2, serializedInt2); - } - - [Fact] - public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() - { - var foo = new NoJsonIntId(123); - - var serialized = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":" + foo.Value + "}"; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() - { - var foo = new NoJsonIntId(123); - - var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); - - var expected = $"\"{foo.Value}\""; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoTypeConverter_SerializesWithValueProperty() - { - var foo = new NoConverterIntId(123); - - var newtonsoft = SystemTextJsonSerializer.Serialize(foo); - var systemText = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":" + foo.Value + "}"; - - Assert.Equal(expected, newtonsoft); - Assert.Equal(expected, systemText); - } - - [Fact] - public void WhenEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - var original = new TestEntity { Id = new EfCoreIntId(123) }; - using (var context = new TestDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add(original); - context.SaveChanges(); - } - using (var context = new TestDbContext(options)) - { - var all = context.Entities.ToList(); - var retrieved = Assert.Single(all); - Assert.Equal(original.Id, retrieved.Id); - } - } - - [Fact] - public async Task WhenDapperValueConverterUsesValueConverter() - { - using var connection = new SqliteConnection("DataSource=:memory:"); - await connection.OpenAsync(); - - var results = await connection.QueryAsync("SELECT 123"); - - var value = Assert.Single(results); - Assert.Equal(new DapperIntId(123), value); - } - - [Theory] - [InlineData(123)] - [InlineData("123")] - public void TypeConverter_CanConvertToAndFrom(object value) - { - var converter = TypeDescriptor.GetConverter(typeof(NoJsonIntId)); - var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new NoJsonIntId(123), id); - - var reconverted = converter.ConvertTo(id, value.GetType()); - Assert.Equal(value, reconverted); - } - - [Fact] - public void CanCompareDefaults() - { - ComparableIntId original = default; - var other = ComparableIntId.Empty; - - var compare1 = original.CompareTo(other); - var compare2 = other.CompareTo(original); - Assert.Equal(compare1, -compare2); - } - - [Fact] - public void CanEquateDefaults() - { - EquatableIntId original = default; - var other = EquatableIntId.Empty; - - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); - - Assert.Equal(equals1, equals2); - } - - [Fact] - public void ImplementsInterfaces() - { - Assert.IsAssignableFrom>(BothIntId.Empty); - Assert.IsAssignableFrom>(BothIntId.Empty); - - Assert.IsAssignableFrom>(EquatableIntId.Empty); - Assert.IsAssignableFrom>(ComparableIntId.Empty); - -#pragma warning disable 184 - Assert.False(IntId.Empty is IComparable); - Assert.False(IntId.Empty is IEquatable); -#pragma warning restore 184 - } - - -#if NET6_0_OR_GREATER - [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - using (var context = new ConventionsDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity { Id = new EfCoreIntId(123) }); - context.SaveChanges(); - } - using (var context = new ConventionsDbContext(options)) - { - var all = context.Entities.ToList(); - Assert.Single(all); - } - } - - public class ConventionsDbContext : DbContext - { - public DbSet Entities { get; set; } - - public ConventionsDbContext(DbContextOptions options) : base(options) - { - } - - protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) - { - configurationBuilder - .Properties() - .HaveConversion(); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .ValueGeneratedNever(); - }); - } - } -#endif - - public class TestDbContext : DbContext - { - public DbSet Entities { get; set; } - - public TestDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .HasConversion(new EfCoreIntId.EfCoreValueConverter()) - .ValueGeneratedNever(); - }); - } - } - - public class TestEntity - { - public EfCoreIntId Id { get; set; } - } - - public class EntityWithNullableId - { - public NewtonsoftJsonIntId? Id { get; set; } - } - } -} \ No newline at end of file +// using System; +// using System.ComponentModel; +// using System.Linq; +// using System.Threading.Tasks; +// using Dapper; +// using Microsoft.Data.Sqlite; +// using Microsoft.EntityFrameworkCore; +// using StronglyTypedIds.IntegrationTests.Types; +// using Xunit; +// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; +// +// namespace StronglyTypedIds.IntegrationTests +// { +// public class IntIdTests +// { +// [Fact] +// public void SameValuesAreEqual() +// { +// var id = 123; +// var foo1 = new IntId(id); +// var foo2 = new IntId(id); +// +// Assert.Equal(foo1, foo2); +// } +// +// [Fact] +// public void EmptyValueIsEmpty() +// { +// Assert.Equal(0, IntId.Empty.Value); +// } +// +// +// [Fact] +// public void DifferentValuesAreUnequal() +// { +// var foo1 = new IntId(1); +// var foo2 = new IntId(2); +// +// Assert.NotEqual(foo1, foo2); +// } +// +// [Fact] +// public void OverloadsWorkCorrectly() +// { +// var id = 12; +// var same1 = new IntId(id); +// var same2 = new IntId(id); +// var different = new IntId(3); +// +// Assert.True(same1 == same2); +// Assert.False(same1 == different); +// Assert.False(same1 != same2); +// Assert.True(same1 != different); +// } +// +// [Fact] +// public void DifferentTypesAreUnequal() +// { +// var bar = GuidId2.New(); +// var foo = new IntId(23); +// +// //Assert.NotEqual(bar, foo); // does not compile +// Assert.NotEqual((object)bar, (object)foo); +// } +// +// [Fact] +// public void CanSerializeToInt_WithNewtonsoftJsonProvider() +// { +// var foo = new NewtonsoftJsonIntId(123); +// +// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedInt = NewtonsoftJsonSerializer.SerializeObject(foo.Value); +// +// Assert.Equal(serializedFoo, serializedInt); +// } +// +// [Fact] +// public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() +// { +// var entity = new EntityWithNullableId { Id = null }; +// +// var json = NewtonsoftJsonSerializer.SerializeObject(entity); +// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); +// +// Assert.NotNull(deserialize); +// Assert.Null(deserialize.Id); +// } +// +// [Fact] +// public void CanSerializeToInt_WithSystemTextJsonProvider() +// { +// var foo = new SystemTextJsonIntId(123); +// +// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); +// var serializedInt = SystemTextJsonSerializer.Serialize(foo.Value); +// +// Assert.Equal(serializedFoo, serializedInt); +// } +// +// [Fact] +// public void CanDeserializeFromInt_WithNewtonsoftJsonProvider() +// { +// var value = 123; +// var foo = new NewtonsoftJsonIntId(value); +// var serializedInt = NewtonsoftJsonSerializer.SerializeObject(value); +// +// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedInt); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanDeserializeFromInt_WithSystemTextJsonProvider() +// { +// var value = 123; +// var foo = new SystemTextJsonIntId(value); +// var serializedInt = SystemTextJsonSerializer.Serialize(value); +// +// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedInt); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanSerializeToInt_WithBothJsonConverters() +// { +// var foo = new BothJsonIntId(123); +// +// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedInt1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); +// +// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); +// var serializedInt2 = SystemTextJsonSerializer.Serialize(foo.Value); +// +// Assert.Equal(serializedFoo1, serializedInt1); +// Assert.Equal(serializedFoo2, serializedInt2); +// } +// +// [Fact] +// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() +// { +// var foo = new NoJsonIntId(123); +// +// var serialized = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":" + foo.Value + "}"; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() +// { +// var foo = new NoJsonIntId(123); +// +// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); +// +// var expected = $"\"{foo.Value}\""; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoTypeConverter_SerializesWithValueProperty() +// { +// var foo = new NoConverterIntId(123); +// +// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); +// var systemText = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":" + foo.Value + "}"; +// +// Assert.Equal(expected, newtonsoft); +// Assert.Equal(expected, systemText); +// } +// +// [Fact] +// public void WhenEfCoreValueConverterUsesValueConverter() +// { +// var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// var original = new TestEntity { Id = new EfCoreIntId(123) }; +// using (var context = new TestDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add(original); +// context.SaveChanges(); +// } +// using (var context = new TestDbContext(options)) +// { +// var all = context.Entities.ToList(); +// var retrieved = Assert.Single(all); +// Assert.Equal(original.Id, retrieved.Id); +// } +// } +// +// [Fact] +// public async Task WhenDapperValueConverterUsesValueConverter() +// { +// using var connection = new SqliteConnection("DataSource=:memory:"); +// await connection.OpenAsync(); +// +// var results = await connection.QueryAsync("SELECT 123"); +// +// var value = Assert.Single(results); +// Assert.Equal(new DapperIntId(123), value); +// } +// +// [Theory] +// [InlineData(123)] +// [InlineData("123")] +// public void TypeConverter_CanConvertToAndFrom(object value) +// { +// var converter = TypeDescriptor.GetConverter(typeof(NoJsonIntId)); +// var id = converter.ConvertFrom(value); +// Assert.IsType(id); +// Assert.Equal(new NoJsonIntId(123), id); +// +// var reconverted = converter.ConvertTo(id, value.GetType()); +// Assert.Equal(value, reconverted); +// } +// +// [Fact] +// public void CanCompareDefaults() +// { +// ComparableIntId original = default; +// var other = ComparableIntId.Empty; +// +// var compare1 = original.CompareTo(other); +// var compare2 = other.CompareTo(original); +// Assert.Equal(compare1, -compare2); +// } +// +// [Fact] +// public void CanEquateDefaults() +// { +// EquatableIntId original = default; +// var other = EquatableIntId.Empty; +// +// var equals1 = (original as IEquatable).Equals(other); +// var equals2 = (other as IEquatable).Equals(original); +// +// Assert.Equal(equals1, equals2); +// } +// +// [Fact] +// public void ImplementsInterfaces() +// { +// Assert.IsAssignableFrom>(BothIntId.Empty); +// Assert.IsAssignableFrom>(BothIntId.Empty); +// +// Assert.IsAssignableFrom>(EquatableIntId.Empty); +// Assert.IsAssignableFrom>(ComparableIntId.Empty); +// +// #pragma warning disable 184 +// Assert.False(IntId.Empty is IComparable); +// Assert.False(IntId.Empty is IEquatable); +// #pragma warning restore 184 +// } +// +// +// #if NET6_0_OR_GREATER +// [Fact] +// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() +// { +// var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// using (var context = new ConventionsDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add( +// new TestEntity { Id = new EfCoreIntId(123) }); +// context.SaveChanges(); +// } +// using (var context = new ConventionsDbContext(options)) +// { +// var all = context.Entities.ToList(); +// Assert.Single(all); +// } +// } +// +// public class ConventionsDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public ConventionsDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) +// { +// configurationBuilder +// .Properties() +// .HaveConversion(); +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .ValueGeneratedNever(); +// }); +// } +// } +// #endif +// +// public class TestDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public TestDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .HasConversion(new EfCoreIntId.EfCoreValueConverter()) +// .ValueGeneratedNever(); +// }); +// } +// } +// +// public class TestEntity +// { +// public EfCoreIntId Id { get; set; } +// } +// +// public class EntityWithNullableId +// { +// public NewtonsoftJsonIntId? Id { get; set; } +// } +// } +// } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs index b2f70dbcb..7b940308b 100644 --- a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs @@ -1,353 +1,353 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Threading.Tasks; -using Dapper; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using StronglyTypedIds.IntegrationTests.Types; -using Xunit; -using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; - -namespace StronglyTypedIds.IntegrationTests -{ - public class LongIdTests - { - [Fact] - public void SameValuesAreEqual() - { - var id = 123L; - var foo1 = new LongId(id); - var foo2 = new LongId(id); - - Assert.Equal(foo1, foo2); - } - - [Fact] - public void EmptyValueIsEmpty() - { - Assert.Equal(0, LongId.Empty.Value); - } - - - [Fact] - public void DifferentValuesAreUnequal() - { - var foo1 = new LongId(1L); - var foo2 = new LongId(2L); - - Assert.NotEqual(foo1, foo2); - } - - [Fact] - public void OverloadsWorkCorrectly() - { - var id = 12L; - var same1 = new LongId(id); - var same2 = new LongId(id); - var different = new LongId(3L); - - Assert.True(same1 == same2); - Assert.False(same1 == different); - Assert.False(same1 != same2); - Assert.True(same1 != different); - } - - [Fact] - public void DifferentTypesAreUnequal() - { - var bar = GuidId2.New(); - var foo = new LongId(23L); - - //Assert.NotEqual(bar, foo); // does not compile - Assert.NotEqual((object)bar, (object)foo); - } - - [Fact] - public void CanSerializeToLong_WithNewtonsoftJsonProvider() - { - var foo = new NewtonsoftJsonLongId(123); - - var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedLong = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - Assert.Equal(serializedFoo, serializedLong); - } - - [Fact] - public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() - { - var entity = new EntityWithNullableId { Id = null }; - - var json = NewtonsoftJsonSerializer.SerializeObject(entity); - var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); - - Assert.NotNull(deserialize); - Assert.Null(deserialize.Id); - } - - [Fact] - public void CanSerializeToLong_WithSystemTextJsonProvider() - { - var foo = new SystemTextJsonLongId(123L); - - var serializedFoo = SystemTextJsonSerializer.Serialize(foo); - var serializedLong = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo, serializedLong); - } - - [Fact] - public void CanDeserializeFromLong_WithNewtonsoftJsonProvider() - { - var value = 123L; - var foo = new NewtonsoftJsonLongId(value); - var serializedLong = NewtonsoftJsonSerializer.SerializeObject(value); - - var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedLong); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanDeserializeFromLong_WithSystemTextJsonProvider() - { - var value = 123L; - var foo = new SystemTextJsonLongId(value); - var serializedLong = SystemTextJsonSerializer.Serialize(value); - - var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedLong); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanSerializeToLong_WithBothJsonConverters() - { - var foo = new BothJsonLongId(123L); - - var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedLong1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); - var serializedLong2 = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo1, serializedLong1); - Assert.Equal(serializedFoo2, serializedLong2); - } - - [Fact] - public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() - { - var foo = new NoJsonLongId(123); - - var serialized = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":" + foo.Value + "}"; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() - { - var foo = new NoJsonLongId(123); - - var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); - - var expected = $"\"{foo.Value}\""; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoTypeConverter_SerializesWithValueProperty() - { - var foo = new NoConverterLongId(123); - - var newtonsoft = SystemTextJsonSerializer.Serialize(foo); - var systemText = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":" + foo.Value + "}"; - - Assert.Equal(expected, newtonsoft); - Assert.Equal(expected, systemText); - } - - [Fact] - public void WhenEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - var original = new TestEntity { Id = new EfCoreLongId(123) }; - using (var context = new TestDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add(original); - context.SaveChanges(); - } - - using (var context = new TestDbContext(options)) - { - var all = context.Entities.ToList(); - var retrieved = Assert.Single(all); - Assert.Equal(original.Id, retrieved.Id); - } - } - - [Fact] - public async Task WhenDapperValueConverterUsesValueConverter() - { - using var connection = new SqliteConnection("DataSource=:memory:"); - await connection.OpenAsync(); - - var results = await connection.QueryAsync("SELECT 123"); - - var value = Assert.Single(results); - Assert.Equal(value, new DapperLongId(123)); - } - - [Theory] - [InlineData(123L)] - [InlineData("123")] - public void TypeConverter_CanConvertToAndFrom(object value) - { - var converter = TypeDescriptor.GetConverter(typeof(NoJsonLongId)); - var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new NoJsonLongId(123), id); - - var reconverted = converter.ConvertTo(id, value.GetType()); - Assert.Equal(value, reconverted); - } - - [Fact] - public void CanCompareDefaults() - { - ComparableLongId original = default; - var other = ComparableLongId.Empty; - - var compare1 = original.CompareTo(other); - var compare2 = other.CompareTo(original); - Assert.Equal(compare1, -compare2); - } - - [Fact] - public void CanEquateDefaults() - { - EquatableLongId original = default; - var other = EquatableLongId.Empty; - - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); - - Assert.Equal(equals1, equals2); - } - - [Fact] - public void ImplementsInterfaces() - { - Assert.IsAssignableFrom>(BothLongId.Empty); - Assert.IsAssignableFrom>(BothLongId.Empty); - - Assert.IsAssignableFrom>(EquatableLongId.Empty); - Assert.IsAssignableFrom>(ComparableLongId.Empty); - -#pragma warning disable 184 - Assert.False(LongId.Empty is IComparable); - Assert.False(LongId.Empty is IEquatable); -#pragma warning restore 184 - } - - -#if NET6_0_OR_GREATER - [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - using (var context = new ConventionsDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity { Id = new EfCoreLongId(123) }); - context.SaveChanges(); - } - using (var context = new ConventionsDbContext(options)) - { - var all = context.Entities.ToList(); - Assert.Single(all); - } - } - - public class ConventionsDbContext : DbContext - { - public DbSet Entities { get; set; } - - public ConventionsDbContext(DbContextOptions options) : base(options) - { - } - - protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) - { - configurationBuilder - .Properties() - .HaveConversion(); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .ValueGeneratedNever(); - }); - } - } -#endif - - public class TestDbContext : DbContext - { - public DbSet Entities { get; set; } - - public TestDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .HasConversion(new EfCoreLongId.EfCoreValueConverter()) - .ValueGeneratedNever(); - }); - } - } - - public class TestEntity - { - public EfCoreLongId Id { get; set; } - } - - public class EntityWithNullableId - { - public NewtonsoftJsonLongId? Id { get; set; } - } - } -} \ No newline at end of file +// using System; +// using System.ComponentModel; +// using System.Linq; +// using System.Threading.Tasks; +// using Dapper; +// using Microsoft.Data.Sqlite; +// using Microsoft.EntityFrameworkCore; +// using StronglyTypedIds.IntegrationTests.Types; +// using Xunit; +// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; +// +// namespace StronglyTypedIds.IntegrationTests +// { +// public class LongIdTests +// { +// [Fact] +// public void SameValuesAreEqual() +// { +// var id = 123L; +// var foo1 = new LongId(id); +// var foo2 = new LongId(id); +// +// Assert.Equal(foo1, foo2); +// } +// +// [Fact] +// public void EmptyValueIsEmpty() +// { +// Assert.Equal(0, LongId.Empty.Value); +// } +// +// +// [Fact] +// public void DifferentValuesAreUnequal() +// { +// var foo1 = new LongId(1L); +// var foo2 = new LongId(2L); +// +// Assert.NotEqual(foo1, foo2); +// } +// +// [Fact] +// public void OverloadsWorkCorrectly() +// { +// var id = 12L; +// var same1 = new LongId(id); +// var same2 = new LongId(id); +// var different = new LongId(3L); +// +// Assert.True(same1 == same2); +// Assert.False(same1 == different); +// Assert.False(same1 != same2); +// Assert.True(same1 != different); +// } +// +// [Fact] +// public void DifferentTypesAreUnequal() +// { +// var bar = GuidId2.New(); +// var foo = new LongId(23L); +// +// //Assert.NotEqual(bar, foo); // does not compile +// Assert.NotEqual((object)bar, (object)foo); +// } +// +// [Fact] +// public void CanSerializeToLong_WithNewtonsoftJsonProvider() +// { +// var foo = new NewtonsoftJsonLongId(123); +// +// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedLong = NewtonsoftJsonSerializer.SerializeObject(foo.Value); +// +// Assert.Equal(serializedFoo, serializedLong); +// } +// +// [Fact] +// public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() +// { +// var entity = new EntityWithNullableId { Id = null }; +// +// var json = NewtonsoftJsonSerializer.SerializeObject(entity); +// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); +// +// Assert.NotNull(deserialize); +// Assert.Null(deserialize.Id); +// } +// +// [Fact] +// public void CanSerializeToLong_WithSystemTextJsonProvider() +// { +// var foo = new SystemTextJsonLongId(123L); +// +// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); +// var serializedLong = SystemTextJsonSerializer.Serialize(foo.Value); +// +// Assert.Equal(serializedFoo, serializedLong); +// } +// +// [Fact] +// public void CanDeserializeFromLong_WithNewtonsoftJsonProvider() +// { +// var value = 123L; +// var foo = new NewtonsoftJsonLongId(value); +// var serializedLong = NewtonsoftJsonSerializer.SerializeObject(value); +// +// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedLong); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanDeserializeFromLong_WithSystemTextJsonProvider() +// { +// var value = 123L; +// var foo = new SystemTextJsonLongId(value); +// var serializedLong = SystemTextJsonSerializer.Serialize(value); +// +// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedLong); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanSerializeToLong_WithBothJsonConverters() +// { +// var foo = new BothJsonLongId(123L); +// +// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedLong1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); +// +// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); +// var serializedLong2 = SystemTextJsonSerializer.Serialize(foo.Value); +// +// Assert.Equal(serializedFoo1, serializedLong1); +// Assert.Equal(serializedFoo2, serializedLong2); +// } +// +// [Fact] +// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() +// { +// var foo = new NoJsonLongId(123); +// +// var serialized = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":" + foo.Value + "}"; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() +// { +// var foo = new NoJsonLongId(123); +// +// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); +// +// var expected = $"\"{foo.Value}\""; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoTypeConverter_SerializesWithValueProperty() +// { +// var foo = new NoConverterLongId(123); +// +// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); +// var systemText = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":" + foo.Value + "}"; +// +// Assert.Equal(expected, newtonsoft); +// Assert.Equal(expected, systemText); +// } +// +// [Fact] +// public void WhenEfCoreValueConverterUsesValueConverter() +// { +// var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// var original = new TestEntity { Id = new EfCoreLongId(123) }; +// using (var context = new TestDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add(original); +// context.SaveChanges(); +// } +// +// using (var context = new TestDbContext(options)) +// { +// var all = context.Entities.ToList(); +// var retrieved = Assert.Single(all); +// Assert.Equal(original.Id, retrieved.Id); +// } +// } +// +// [Fact] +// public async Task WhenDapperValueConverterUsesValueConverter() +// { +// using var connection = new SqliteConnection("DataSource=:memory:"); +// await connection.OpenAsync(); +// +// var results = await connection.QueryAsync("SELECT 123"); +// +// var value = Assert.Single(results); +// Assert.Equal(value, new DapperLongId(123)); +// } +// +// [Theory] +// [InlineData(123L)] +// [InlineData("123")] +// public void TypeConverter_CanConvertToAndFrom(object value) +// { +// var converter = TypeDescriptor.GetConverter(typeof(NoJsonLongId)); +// var id = converter.ConvertFrom(value); +// Assert.IsType(id); +// Assert.Equal(new NoJsonLongId(123), id); +// +// var reconverted = converter.ConvertTo(id, value.GetType()); +// Assert.Equal(value, reconverted); +// } +// +// [Fact] +// public void CanCompareDefaults() +// { +// ComparableLongId original = default; +// var other = ComparableLongId.Empty; +// +// var compare1 = original.CompareTo(other); +// var compare2 = other.CompareTo(original); +// Assert.Equal(compare1, -compare2); +// } +// +// [Fact] +// public void CanEquateDefaults() +// { +// EquatableLongId original = default; +// var other = EquatableLongId.Empty; +// +// var equals1 = (original as IEquatable).Equals(other); +// var equals2 = (other as IEquatable).Equals(original); +// +// Assert.Equal(equals1, equals2); +// } +// +// [Fact] +// public void ImplementsInterfaces() +// { +// Assert.IsAssignableFrom>(BothLongId.Empty); +// Assert.IsAssignableFrom>(BothLongId.Empty); +// +// Assert.IsAssignableFrom>(EquatableLongId.Empty); +// Assert.IsAssignableFrom>(ComparableLongId.Empty); +// +// #pragma warning disable 184 +// Assert.False(LongId.Empty is IComparable); +// Assert.False(LongId.Empty is IEquatable); +// #pragma warning restore 184 +// } +// +// +// #if NET6_0_OR_GREATER +// [Fact] +// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() +// { +// var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// using (var context = new ConventionsDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add( +// new TestEntity { Id = new EfCoreLongId(123) }); +// context.SaveChanges(); +// } +// using (var context = new ConventionsDbContext(options)) +// { +// var all = context.Entities.ToList(); +// Assert.Single(all); +// } +// } +// +// public class ConventionsDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public ConventionsDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) +// { +// configurationBuilder +// .Properties() +// .HaveConversion(); +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .ValueGeneratedNever(); +// }); +// } +// } +// #endif +// +// public class TestDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public TestDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .HasConversion(new EfCoreLongId.EfCoreValueConverter()) +// .ValueGeneratedNever(); +// }); +// } +// } +// +// public class TestEntity +// { +// public EfCoreLongId Id { get; set; } +// } +// +// public class EntityWithNullableId +// { +// public NewtonsoftJsonLongId? Id { get; set; } +// } +// } +// } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs b/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs index e6dce6d74..88d9292f0 100644 --- a/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs @@ -1,361 +1,361 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Threading.Tasks; -using Dapper; -using MassTransit; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using StronglyTypedIds.IntegrationTests.Types; -using Xunit; -using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; - -namespace StronglyTypedIds.IntegrationTests -{ - public class MassTransitNewIdTests - { - [Fact] - public void SameValuesAreEqual() - { - var id = NewId.Next(); - var foo1 = new NewIdId1(id); - var foo2 = new NewIdId1(id); - - Assert.Equal(foo1, foo2); - } - - [Fact] - public void EmptyValueIsEmpty() - { - Assert.Equal(NewIdId1.Empty.Value, NewId.Empty); - } - - - [Fact] - public void DifferentValuesAreUnequal() - { - var foo1 = NewIdId1.New(); - var foo2 = NewIdId1.New(); - - Assert.NotEqual(foo1, foo2); - } - - [Fact] - public void OverloadsWorkCorrectly() - { - var id = NewId.Next(); - var same1 = new NewIdId1(id); - var same2 = new NewIdId1(id); - var different = NewIdId1.New(); - - Assert.True(same1 == same2); - Assert.False(same1 == different); - Assert.False(same1 != same2); - Assert.True(same1 != different); - } - - [Fact] - public void DifferentTypesAreUnequal() - { - var bar = NewIdId2.New(); - var foo = NewIdId1.New(); - - //Assert.NotEqual(bar, foo); // does not compile - Assert.NotEqual((object)bar, (object)foo); - } - - [Fact] - public void CantCreateEmptyGeneratedId1() - { - var foo = new NewIdId1(); - var bar = new NewIdId2(); - - //Assert.NotEqual(bar, foo); // does not compile - Assert.NotEqual((object)bar, (object)foo); - } - - [Fact] - public void CanSerializeToNewId_WithTypeConverter() - { - var foo = NewtonsoftJsonNewIdId.New(); - - var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedNewId = NewtonsoftJsonSerializer.SerializeObject(foo.Value.ToGuid()); - - Assert.Equal(serializedFoo, serializedNewId); - } - - [Fact] - public void CanSerializeToNewId_WithSystemTextJsonProvider() - { - var foo = SystemTextJsonNewIdId.New(); - - var serializedFoo = SystemTextJsonSerializer.Serialize(foo); - var serializedNewId = SystemTextJsonSerializer.Serialize(foo.Value.ToGuid().ToString()); - - Assert.Equal(serializedFoo, serializedNewId); - } - - [Fact] - public void CanDeserializeFromNewId_WithNewtonsoftJsonProvider() - { - var value = NewId.Next(); - var foo = new NewtonsoftJsonNewIdId(value); - var serializedNewId = NewtonsoftJsonSerializer.SerializeObject(value.ToGuid()); - - var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedNewId); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() - { - var entity = new EntityWithNullableId { Id = null }; - - var json = NewtonsoftJsonSerializer.SerializeObject(entity); - var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); - - Assert.NotNull(deserialize); - Assert.Null(deserialize.Id); - } - - [Fact] - public void CanDeserializeFromNewId_WithSystemTextJsonProvider() - { - var value = NewId.Next(); - var foo = new SystemTextJsonNewIdId(value); - var serializedNewId = SystemTextJsonSerializer.Serialize(value.ToGuid()); - - var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedNewId); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanSerializeToNewId_WithBothJsonConverters() - { - var foo = BothJsonNewIdId.New(); - - var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedNewId1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value.ToGuid().ToString()); - - var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); - var serializedNewId2 = SystemTextJsonSerializer.Serialize(foo.Value.ToGuid().ToString()); - - Assert.Equal(serializedFoo1, serializedNewId1); - Assert.Equal(serializedFoo2, serializedNewId2); - } - - [Fact] - public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() - { - var foo = NoJsonNewIdId.New(); - - var serialized = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":" + SystemTextJsonSerializer.Serialize(foo.Value) + "}"; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() - { - var foo = NoJsonNewIdId.New(); - - var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); - - var expected = $"\"{foo.Value.ToGuid()}\""; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoTypeConverter_SerializesWithValueProperty() - { - var foo = NoConverterNewIdId.New(); - - var newtonsoft = SystemTextJsonSerializer.Serialize(foo); - var systemText = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":" + SystemTextJsonSerializer.Serialize(foo.Value) + "}"; - - Assert.Equal(expected, newtonsoft); - Assert.Equal(expected, systemText); - } - - [Fact] - public void WhenEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - using (var context = new TestDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity { Id = EfCoreNewIdId.New() }); - context.SaveChanges(); - } - using (var context = new TestDbContext(options)) - { - var all = context.Entities.ToList(); - Assert.Single(all); - } - } - - [Fact] - public async Task WhenDapperValueConverterUsesValueConverter() - { - using var connection = new SqliteConnection("DataSource=:memory:"); - await connection.OpenAsync(); - - var results = await connection.QueryAsync("SELECT '5640dad4-862a-4738-9e3c-c76dc227eb66'"); - - var value = Assert.Single(results); - Assert.Equal(new DapperNewIdId(NewId.FromGuid(Guid.Parse("5640dad4-862a-4738-9e3c-c76dc227eb66"))), value); - } - - [Theory] - [InlineData("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")] - public void TypeConverter_CanConvertToAndFrom(string value) - { - var converter = TypeDescriptor.GetConverter(typeof(NoJsonNewIdId)); - var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new NoJsonNewIdId(NewId.FromGuid(Guid.Parse(value))), id); - - var reconverted = converter.ConvertTo(id, value.GetType()); - Assert.Equal(value, reconverted); - } - - [Fact] - public void CanCompareDefaults() - { - ComparableNewIdId original = default; - var other = ComparableNewIdId.Empty; - - var compare1 = original.CompareTo(other); - var compare2 = other.CompareTo(original); - Assert.Equal(compare1, -compare2); - } - - [Fact] - public void CanEquateDefaults() - { - EquatableNewIdId original = default; - var other = EquatableNewIdId.Empty; - - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); - - Assert.Equal(equals1, equals2); - } - - [Fact] - public void ImplementsInterfaces() - { - Assert.IsAssignableFrom>(BothNewIdId.Empty); - Assert.IsAssignableFrom>(BothNewIdId.Empty); - - Assert.IsAssignableFrom>(EquatableNewIdId.Empty); - Assert.IsAssignableFrom>(ComparableNewIdId.Empty); - -#pragma warning disable 184 - Assert.False(NewIdId1.Empty is IComparable); - Assert.False(NewIdId1.Empty is IEquatable); -#pragma warning restore 184 - } - - -#if NET6_0_OR_GREATER - [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - using (var context = new ConventionsDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity { Id = EfCoreNewIdId.New() }); - context.SaveChanges(); - } - using (var context = new ConventionsDbContext(options)) - { - var all = context.Entities.ToList(); - Assert.Single(all); - } - } - - public class ConventionsDbContext : DbContext - { - public DbSet Entities { get; set; } - - public ConventionsDbContext(DbContextOptions options) : base(options) - { - } - - protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) - { - configurationBuilder - .Properties() - .HaveConversion(); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .ValueGeneratedNever(); - }); - } - } -#endif - - public class TestDbContext : DbContext - { - public DbSet Entities { get; set; } - - public TestDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .HasConversion(new EfCoreNewIdId.EfCoreValueConverter()) - .ValueGeneratedNever(); - }); - } - } - - public class TestEntity - { - public EfCoreNewIdId Id { get; set; } - } - - public class EntityWithNullableId - { - public NewtonsoftJsonNewIdId? Id { get; set; } - } - } -} \ No newline at end of file +// using System; +// using System.ComponentModel; +// using System.Linq; +// using System.Threading.Tasks; +// using Dapper; +// using MassTransit; +// using Microsoft.Data.Sqlite; +// using Microsoft.EntityFrameworkCore; +// using StronglyTypedIds.IntegrationTests.Types; +// using Xunit; +// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; +// +// namespace StronglyTypedIds.IntegrationTests +// { +// public class MassTransitNewIdTests +// { +// [Fact] +// public void SameValuesAreEqual() +// { +// var id = NewId.Next(); +// var foo1 = new NewIdId1(id); +// var foo2 = new NewIdId1(id); +// +// Assert.Equal(foo1, foo2); +// } +// +// [Fact] +// public void EmptyValueIsEmpty() +// { +// Assert.Equal(NewIdId1.Empty.Value, NewId.Empty); +// } +// +// +// [Fact] +// public void DifferentValuesAreUnequal() +// { +// var foo1 = NewIdId1.New(); +// var foo2 = NewIdId1.New(); +// +// Assert.NotEqual(foo1, foo2); +// } +// +// [Fact] +// public void OverloadsWorkCorrectly() +// { +// var id = NewId.Next(); +// var same1 = new NewIdId1(id); +// var same2 = new NewIdId1(id); +// var different = NewIdId1.New(); +// +// Assert.True(same1 == same2); +// Assert.False(same1 == different); +// Assert.False(same1 != same2); +// Assert.True(same1 != different); +// } +// +// [Fact] +// public void DifferentTypesAreUnequal() +// { +// var bar = NewIdId2.New(); +// var foo = NewIdId1.New(); +// +// //Assert.NotEqual(bar, foo); // does not compile +// Assert.NotEqual((object)bar, (object)foo); +// } +// +// [Fact] +// public void CantCreateEmptyGeneratedId1() +// { +// var foo = new NewIdId1(); +// var bar = new NewIdId2(); +// +// //Assert.NotEqual(bar, foo); // does not compile +// Assert.NotEqual((object)bar, (object)foo); +// } +// +// [Fact] +// public void CanSerializeToNewId_WithTypeConverter() +// { +// var foo = NewtonsoftJsonNewIdId.New(); +// +// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedNewId = NewtonsoftJsonSerializer.SerializeObject(foo.Value.ToGuid()); +// +// Assert.Equal(serializedFoo, serializedNewId); +// } +// +// [Fact] +// public void CanSerializeToNewId_WithSystemTextJsonProvider() +// { +// var foo = SystemTextJsonNewIdId.New(); +// +// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); +// var serializedNewId = SystemTextJsonSerializer.Serialize(foo.Value.ToGuid().ToString()); +// +// Assert.Equal(serializedFoo, serializedNewId); +// } +// +// [Fact] +// public void CanDeserializeFromNewId_WithNewtonsoftJsonProvider() +// { +// var value = NewId.Next(); +// var foo = new NewtonsoftJsonNewIdId(value); +// var serializedNewId = NewtonsoftJsonSerializer.SerializeObject(value.ToGuid()); +// +// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedNewId); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() +// { +// var entity = new EntityWithNullableId { Id = null }; +// +// var json = NewtonsoftJsonSerializer.SerializeObject(entity); +// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); +// +// Assert.NotNull(deserialize); +// Assert.Null(deserialize.Id); +// } +// +// [Fact] +// public void CanDeserializeFromNewId_WithSystemTextJsonProvider() +// { +// var value = NewId.Next(); +// var foo = new SystemTextJsonNewIdId(value); +// var serializedNewId = SystemTextJsonSerializer.Serialize(value.ToGuid()); +// +// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedNewId); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanSerializeToNewId_WithBothJsonConverters() +// { +// var foo = BothJsonNewIdId.New(); +// +// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedNewId1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value.ToGuid().ToString()); +// +// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); +// var serializedNewId2 = SystemTextJsonSerializer.Serialize(foo.Value.ToGuid().ToString()); +// +// Assert.Equal(serializedFoo1, serializedNewId1); +// Assert.Equal(serializedFoo2, serializedNewId2); +// } +// +// [Fact] +// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() +// { +// var foo = NoJsonNewIdId.New(); +// +// var serialized = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":" + SystemTextJsonSerializer.Serialize(foo.Value) + "}"; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() +// { +// var foo = NoJsonNewIdId.New(); +// +// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); +// +// var expected = $"\"{foo.Value.ToGuid()}\""; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoTypeConverter_SerializesWithValueProperty() +// { +// var foo = NoConverterNewIdId.New(); +// +// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); +// var systemText = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":" + SystemTextJsonSerializer.Serialize(foo.Value) + "}"; +// +// Assert.Equal(expected, newtonsoft); +// Assert.Equal(expected, systemText); +// } +// +// [Fact] +// public void WhenEfCoreValueConverterUsesValueConverter() +// { +// var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// using (var context = new TestDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add( +// new TestEntity { Id = EfCoreNewIdId.New() }); +// context.SaveChanges(); +// } +// using (var context = new TestDbContext(options)) +// { +// var all = context.Entities.ToList(); +// Assert.Single(all); +// } +// } +// +// [Fact] +// public async Task WhenDapperValueConverterUsesValueConverter() +// { +// using var connection = new SqliteConnection("DataSource=:memory:"); +// await connection.OpenAsync(); +// +// var results = await connection.QueryAsync("SELECT '5640dad4-862a-4738-9e3c-c76dc227eb66'"); +// +// var value = Assert.Single(results); +// Assert.Equal(new DapperNewIdId(NewId.FromGuid(Guid.Parse("5640dad4-862a-4738-9e3c-c76dc227eb66"))), value); +// } +// +// [Theory] +// [InlineData("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")] +// public void TypeConverter_CanConvertToAndFrom(string value) +// { +// var converter = TypeDescriptor.GetConverter(typeof(NoJsonNewIdId)); +// var id = converter.ConvertFrom(value); +// Assert.IsType(id); +// Assert.Equal(new NoJsonNewIdId(NewId.FromGuid(Guid.Parse(value))), id); +// +// var reconverted = converter.ConvertTo(id, value.GetType()); +// Assert.Equal(value, reconverted); +// } +// +// [Fact] +// public void CanCompareDefaults() +// { +// ComparableNewIdId original = default; +// var other = ComparableNewIdId.Empty; +// +// var compare1 = original.CompareTo(other); +// var compare2 = other.CompareTo(original); +// Assert.Equal(compare1, -compare2); +// } +// +// [Fact] +// public void CanEquateDefaults() +// { +// EquatableNewIdId original = default; +// var other = EquatableNewIdId.Empty; +// +// var equals1 = (original as IEquatable).Equals(other); +// var equals2 = (other as IEquatable).Equals(original); +// +// Assert.Equal(equals1, equals2); +// } +// +// [Fact] +// public void ImplementsInterfaces() +// { +// Assert.IsAssignableFrom>(BothNewIdId.Empty); +// Assert.IsAssignableFrom>(BothNewIdId.Empty); +// +// Assert.IsAssignableFrom>(EquatableNewIdId.Empty); +// Assert.IsAssignableFrom>(ComparableNewIdId.Empty); +// +// #pragma warning disable 184 +// Assert.False(NewIdId1.Empty is IComparable); +// Assert.False(NewIdId1.Empty is IEquatable); +// #pragma warning restore 184 +// } +// +// +// #if NET6_0_OR_GREATER +// [Fact] +// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() +// { +// var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// using (var context = new ConventionsDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add( +// new TestEntity { Id = EfCoreNewIdId.New() }); +// context.SaveChanges(); +// } +// using (var context = new ConventionsDbContext(options)) +// { +// var all = context.Entities.ToList(); +// Assert.Single(all); +// } +// } +// +// public class ConventionsDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public ConventionsDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) +// { +// configurationBuilder +// .Properties() +// .HaveConversion(); +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .ValueGeneratedNever(); +// }); +// } +// } +// #endif +// +// public class TestDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public TestDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .HasConversion(new EfCoreNewIdId.EfCoreValueConverter()) +// .ValueGeneratedNever(); +// }); +// } +// } +// +// public class TestEntity +// { +// public EfCoreNewIdId Id { get; set; } +// } +// +// public class EntityWithNullableId +// { +// public NewtonsoftJsonNewIdId? Id { get; set; } +// } +// } +// } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/NestedIdTests.cs b/test/StronglyTypedIds.IntegrationTests/NestedIdTests.cs index c58336747..173417743 100644 --- a/test/StronglyTypedIds.IntegrationTests/NestedIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/NestedIdTests.cs @@ -5,9 +5,9 @@ namespace StronglyTypedIds.IntegrationTests; public class NestedIdTests { - [Fact] - public void CanCreateNestedId() - { - var id = SomeType.NestedType.MoreNesting.VeryNestedId.New(); - } + // [Fact] + // public void CanCreateNestedId() + // { + // var id = SomeType.NestedType.MoreNesting.VeryNestedId.New(); + // } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs index c6835af82..906e9367e 100644 --- a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs @@ -1,431 +1,431 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Threading.Tasks; -using Dapper; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using StronglyTypedIds.IntegrationTests.Types; -using Xunit; -using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; - -namespace StronglyTypedIds.IntegrationTests -{ - public class NullableStringIdTests - { - [Fact] - public void SameValuesAreEqual() - { - var id = "some-value"; - var foo1 = new NullableStringId(id); - var foo2 = new NullableStringId(id); - - Assert.Equal(foo1, foo2); - } - - [Fact] - public void EmptyValueIsEmpty() - { - Assert.Equal(NullableStringId.Empty.Value, string.Empty); - } - - - [Fact] - public void DifferentValuesAreUnequal() - { - var foo1 = new NullableStringId("value1"); - var foo2 = new NullableStringId("value2"); - - Assert.NotEqual(foo1, foo2); - } - - [Fact] - public void OverloadsWorkCorrectly() - { - var id = "some-value"; - var same1 = new NullableStringId(id); - var same2 = new NullableStringId(id); - var different = new NullableStringId("other value"); - - Assert.True(same1 == same2); - Assert.False(same1 == different); - Assert.False(same1 != same2); - Assert.True(same1 != different); - } - - [Fact] - public void DifferentTypesAreUnequal() - { - var bar = GuidId2.New(); - var foo = new NullableStringId("Value"); - - //Assert.NotEqual(bar, foo); // does not compile - Assert.NotEqual((object)bar, (object)foo); - } - - [Fact] - public void CanSerializeToString_WithNewtonsoftJsonProvider() - { - var foo = new NewtonsoftJsonNullableStringId("123"); - - var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - Assert.Equal(serializedFoo, serializedString); - } - - [Fact] - public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() - { - var entity = new EntityWithNullableId { Id = null }; - - var json = NewtonsoftJsonSerializer.SerializeObject(entity); - var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); - - Assert.NotNull(deserialize); - // Note the different behaviour from String ID - this will _always_ deserialize to an ID - Assert.NotNull(deserialize.Id); - Assert.Null(deserialize.Id.Value.Value); - } - - [Fact] - public void CanSerializeToString_WithSystemTextJsonProvider() - { - var foo = new SystemTextJsonNullableStringId("123"); - - var serializedFoo = SystemTextJsonSerializer.Serialize(foo); - var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo, serializedString); - } - - [Fact] - public void CanDeserializeFromString_WithNewtonsoftJsonProvider() - { - var value = "123"; - var foo = new NewtonsoftJsonNullableStringId(value); - var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); - - var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanDeserializeFromString_WithSystemTextJsonProvider() - { - var value = "123"; - var foo = new SystemTextJsonNullableStringId(value); - var serializedString = SystemTextJsonSerializer.Serialize(value); - - var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanSerializeToString_WithBothJsonConverters() - { - var foo = new BothJsonNullableStringId("123"); - - var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedString1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); - var serializedString2 = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo1, serializedString1); - Assert.Equal(serializedFoo2, serializedString2); - } - - [Fact] - public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() - { - var foo = new NoJsonNullableStringId("123"); - - var serialized = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":\"" + foo.Value + "\"}"; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() - { - var foo = new NoJsonNullableStringId("123"); - - var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); - - var expected = "\"" + foo.Value + "\""; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoTypeConverter_SerializesWithValueProperty() - { - var foo = new NoConvertersNullableStringId("123"); - - var newtonsoft = SystemTextJsonSerializer.Serialize(foo); - var systemText = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":\"" + foo.Value + "\"}"; - - Assert.Equal(expected, newtonsoft); - Assert.Equal(expected, systemText); - } - - [Fact] - public void WhenEfCoreValueConverterUsesValueConverter() - { - using var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreNullableStringId("some name") }; - using (var context = new TestDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add(original); - context.SaveChanges(); - } - - using (var context = new TestDbContext(options)) - { - var all = context.Entities.ToList(); - var retrieved = Assert.Single(all); - Assert.Equal(original.Id, retrieved.Id); - Assert.Equal(original.Name, retrieved.Name); - } - } - - [Fact] - public async Task WhenDapperValueConverterUsesValueConverter() - { - using var connection = new SqliteConnection("DataSource=:memory:"); - await connection.OpenAsync(); - - var results = await connection.QueryAsync("SELECT 'this is a value'"); - - var value = Assert.Single(results); - Assert.Equal(value, new DapperNullableStringId("this is a value")); - } - - [Theory] - [InlineData("")] - [InlineData("some value")] - public void TypeConverter_CanConvertToAndFrom(object value) - { - var converter = TypeDescriptor.GetConverter(typeof(NoJsonNullableStringId)); - var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new NoJsonNullableStringId(value?.ToString()), id); - - var reconverted = converter.ConvertTo(id, value.GetType()); - Assert.Equal(value, reconverted); - } - - [Fact] - public void CanCompareDefaults() - { - ComparableNullableStringId original = default; - var other = ComparableNullableStringId.Empty; - - var compare1 = original.CompareTo(other); - var compare2 = other.CompareTo(original); - Assert.Equal(compare1, -compare2); - } - - [Fact] - public void CanEquateDefaults() - { - EquatableNullableStringId original = default; - var other = EquatableNullableStringId.Empty; - - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); - - Assert.Equal(equals1, equals2); - } - - [Fact] - public void ImplementsInterfaces() - { - Assert.IsAssignableFrom>(BothNullableStringId.Empty); - Assert.IsAssignableFrom>(BothNullableStringId.Empty); - - Assert.IsAssignableFrom>(EquatableNullableStringId.Empty); - Assert.IsAssignableFrom>(ComparableNullableStringId.Empty); - -#pragma warning disable 184 - Assert.False(NullableStringId.Empty is IComparable); - Assert.False(NullableStringId.Empty is IEquatable); -#pragma warning restore 184 - } - - [Fact] - public void NullValueIsNull() - { - var value = new NullableStringId(null); - Assert.Null(value.Value); - } - - [Fact] - public void CanEquateNullableValues() - { - var value1 = new NullableStringId(null); - var value2 = new NullableStringId(null); - var value3 = new NullableStringId(string.Empty); - - Assert.True(value1.Equals(value2)); - Assert.True(value1.Equals((object)value2)); - - Assert.False(value1.Equals(value3)); - Assert.False(value1.Equals((object)value3)); - Assert.False(value3.Equals((object)value1)); - } - - [Fact] - public void NullHashCodes() - { - var value1 = new NullableStringId(null); - var value2 = new NullableStringId(null); - var value3 = new NullableStringId("something"); - var value4 = new NullableStringId(string.Empty); - - Assert.Equal(value1.GetHashCode(), value2.GetHashCode()); - Assert.NotEqual(value1.GetHashCode(), value3.GetHashCode()); - Assert.NotEqual(value1.GetHashCode(), value4.GetHashCode()); - } - - [Fact] - public void NullSerializesAsExpectedWithoutConverters() - { - var expected = "{\"Value\":null}"; - var value = new NoConvertersNullableStringId(null); - - var json = SystemTextJsonSerializer.Serialize(value); - var systemText = SystemTextJsonSerializer.Serialize(value); - Assert.Equal(expected, json); - Assert.Equal(expected, systemText); - } - - [Fact] - public void NullSerializesAsExpectedWithConverters() - { - var expected = "null"; - var value = new BothJsonNullableStringId(null); - - var json = SystemTextJsonSerializer.Serialize(value); - var systemText = SystemTextJsonSerializer.Serialize(value); - Assert.Equal(expected, systemText); - Assert.Equal(expected, json); - } - - [Fact] - public void TypeConverterConvertsNullAsExpected() - { - var converter = TypeDescriptor.GetConverter(typeof(NoJsonNullableStringId)); - var id = converter.ConvertFrom(null); - Assert.IsType(id); - Assert.Equal(new NoJsonNullableStringId(null), id); - - var reconverted = converter.ConvertTo(id, typeof(string)); - Assert.Null(reconverted); - } - -#if NET6_0_OR_GREATER - [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreNullableStringId("some name") }; - using (var context = new ConventionsDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add(original); - context.SaveChanges(); - } - - using (var context = new ConventionsDbContext(options)) - { - var all = context.Entities.ToList(); - var retrieved = Assert.Single(all); - Assert.Equal(original.Id, retrieved.Id); - Assert.Equal(original.Name, retrieved.Name); - } - } - - public class ConventionsDbContext : DbContext - { - public DbSet Entities { get; set; } - - public ConventionsDbContext(DbContextOptions options) : base(options) - { - } - - protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) - { - configurationBuilder - .Properties() - .HaveConversion(); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .ValueGeneratedNever(); - }); - } - } -#endif - - public class TestDbContext : DbContext - { - public DbSet Entities { get; set; } - - public TestDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Name) - .HasConversion(new EfCoreNullableStringId.EfCoreValueConverter()) - .ValueGeneratedNever(); - }); - } - } - - public class TestEntity - { - public Guid Id { get; set; } - public EfCoreNullableStringId Name { get; set; } - } - - - public class EntityWithNullableId - { - public NewtonsoftJsonNullableStringId? Id { get; set; } - } - } -} \ No newline at end of file +// using System; +// using System.ComponentModel; +// using System.Linq; +// using System.Threading.Tasks; +// using Dapper; +// using Microsoft.Data.Sqlite; +// using Microsoft.EntityFrameworkCore; +// using StronglyTypedIds.IntegrationTests.Types; +// using Xunit; +// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; +// +// namespace StronglyTypedIds.IntegrationTests +// { +// public class NullableStringIdTests +// { +// [Fact] +// public void SameValuesAreEqual() +// { +// var id = "some-value"; +// var foo1 = new NullableStringId(id); +// var foo2 = new NullableStringId(id); +// +// Assert.Equal(foo1, foo2); +// } +// +// [Fact] +// public void EmptyValueIsEmpty() +// { +// Assert.Equal(NullableStringId.Empty.Value, string.Empty); +// } +// +// +// [Fact] +// public void DifferentValuesAreUnequal() +// { +// var foo1 = new NullableStringId("value1"); +// var foo2 = new NullableStringId("value2"); +// +// Assert.NotEqual(foo1, foo2); +// } +// +// [Fact] +// public void OverloadsWorkCorrectly() +// { +// var id = "some-value"; +// var same1 = new NullableStringId(id); +// var same2 = new NullableStringId(id); +// var different = new NullableStringId("other value"); +// +// Assert.True(same1 == same2); +// Assert.False(same1 == different); +// Assert.False(same1 != same2); +// Assert.True(same1 != different); +// } +// +// [Fact] +// public void DifferentTypesAreUnequal() +// { +// var bar = GuidId2.New(); +// var foo = new NullableStringId("Value"); +// +// //Assert.NotEqual(bar, foo); // does not compile +// Assert.NotEqual((object)bar, (object)foo); +// } +// +// [Fact] +// public void CanSerializeToString_WithNewtonsoftJsonProvider() +// { +// var foo = new NewtonsoftJsonNullableStringId("123"); +// +// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); +// +// Assert.Equal(serializedFoo, serializedString); +// } +// +// [Fact] +// public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() +// { +// var entity = new EntityWithNullableId { Id = null }; +// +// var json = NewtonsoftJsonSerializer.SerializeObject(entity); +// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); +// +// Assert.NotNull(deserialize); +// // Note the different behaviour from String ID - this will _always_ deserialize to an ID +// Assert.NotNull(deserialize.Id); +// Assert.Null(deserialize.Id.Value.Value); +// } +// +// [Fact] +// public void CanSerializeToString_WithSystemTextJsonProvider() +// { +// var foo = new SystemTextJsonNullableStringId("123"); +// +// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); +// var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); +// +// Assert.Equal(serializedFoo, serializedString); +// } +// +// [Fact] +// public void CanDeserializeFromString_WithNewtonsoftJsonProvider() +// { +// var value = "123"; +// var foo = new NewtonsoftJsonNullableStringId(value); +// var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); +// +// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanDeserializeFromString_WithSystemTextJsonProvider() +// { +// var value = "123"; +// var foo = new SystemTextJsonNullableStringId(value); +// var serializedString = SystemTextJsonSerializer.Serialize(value); +// +// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanSerializeToString_WithBothJsonConverters() +// { +// var foo = new BothJsonNullableStringId("123"); +// +// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedString1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); +// +// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); +// var serializedString2 = SystemTextJsonSerializer.Serialize(foo.Value); +// +// Assert.Equal(serializedFoo1, serializedString1); +// Assert.Equal(serializedFoo2, serializedString2); +// } +// +// [Fact] +// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() +// { +// var foo = new NoJsonNullableStringId("123"); +// +// var serialized = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":\"" + foo.Value + "\"}"; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() +// { +// var foo = new NoJsonNullableStringId("123"); +// +// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); +// +// var expected = "\"" + foo.Value + "\""; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoTypeConverter_SerializesWithValueProperty() +// { +// var foo = new NoConvertersNullableStringId("123"); +// +// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); +// var systemText = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":\"" + foo.Value + "\"}"; +// +// Assert.Equal(expected, newtonsoft); +// Assert.Equal(expected, systemText); +// } +// +// [Fact] +// public void WhenEfCoreValueConverterUsesValueConverter() +// { +// using var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreNullableStringId("some name") }; +// using (var context = new TestDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add(original); +// context.SaveChanges(); +// } +// +// using (var context = new TestDbContext(options)) +// { +// var all = context.Entities.ToList(); +// var retrieved = Assert.Single(all); +// Assert.Equal(original.Id, retrieved.Id); +// Assert.Equal(original.Name, retrieved.Name); +// } +// } +// +// [Fact] +// public async Task WhenDapperValueConverterUsesValueConverter() +// { +// using var connection = new SqliteConnection("DataSource=:memory:"); +// await connection.OpenAsync(); +// +// var results = await connection.QueryAsync("SELECT 'this is a value'"); +// +// var value = Assert.Single(results); +// Assert.Equal(value, new DapperNullableStringId("this is a value")); +// } +// +// [Theory] +// [InlineData("")] +// [InlineData("some value")] +// public void TypeConverter_CanConvertToAndFrom(object value) +// { +// var converter = TypeDescriptor.GetConverter(typeof(NoJsonNullableStringId)); +// var id = converter.ConvertFrom(value); +// Assert.IsType(id); +// Assert.Equal(new NoJsonNullableStringId(value?.ToString()), id); +// +// var reconverted = converter.ConvertTo(id, value.GetType()); +// Assert.Equal(value, reconverted); +// } +// +// [Fact] +// public void CanCompareDefaults() +// { +// ComparableNullableStringId original = default; +// var other = ComparableNullableStringId.Empty; +// +// var compare1 = original.CompareTo(other); +// var compare2 = other.CompareTo(original); +// Assert.Equal(compare1, -compare2); +// } +// +// [Fact] +// public void CanEquateDefaults() +// { +// EquatableNullableStringId original = default; +// var other = EquatableNullableStringId.Empty; +// +// var equals1 = (original as IEquatable).Equals(other); +// var equals2 = (other as IEquatable).Equals(original); +// +// Assert.Equal(equals1, equals2); +// } +// +// [Fact] +// public void ImplementsInterfaces() +// { +// Assert.IsAssignableFrom>(BothNullableStringId.Empty); +// Assert.IsAssignableFrom>(BothNullableStringId.Empty); +// +// Assert.IsAssignableFrom>(EquatableNullableStringId.Empty); +// Assert.IsAssignableFrom>(ComparableNullableStringId.Empty); +// +// #pragma warning disable 184 +// Assert.False(NullableStringId.Empty is IComparable); +// Assert.False(NullableStringId.Empty is IEquatable); +// #pragma warning restore 184 +// } +// +// [Fact] +// public void NullValueIsNull() +// { +// var value = new NullableStringId(null); +// Assert.Null(value.Value); +// } +// +// [Fact] +// public void CanEquateNullableValues() +// { +// var value1 = new NullableStringId(null); +// var value2 = new NullableStringId(null); +// var value3 = new NullableStringId(string.Empty); +// +// Assert.True(value1.Equals(value2)); +// Assert.True(value1.Equals((object)value2)); +// +// Assert.False(value1.Equals(value3)); +// Assert.False(value1.Equals((object)value3)); +// Assert.False(value3.Equals((object)value1)); +// } +// +// [Fact] +// public void NullHashCodes() +// { +// var value1 = new NullableStringId(null); +// var value2 = new NullableStringId(null); +// var value3 = new NullableStringId("something"); +// var value4 = new NullableStringId(string.Empty); +// +// Assert.Equal(value1.GetHashCode(), value2.GetHashCode()); +// Assert.NotEqual(value1.GetHashCode(), value3.GetHashCode()); +// Assert.NotEqual(value1.GetHashCode(), value4.GetHashCode()); +// } +// +// [Fact] +// public void NullSerializesAsExpectedWithoutConverters() +// { +// var expected = "{\"Value\":null}"; +// var value = new NoConvertersNullableStringId(null); +// +// var json = SystemTextJsonSerializer.Serialize(value); +// var systemText = SystemTextJsonSerializer.Serialize(value); +// Assert.Equal(expected, json); +// Assert.Equal(expected, systemText); +// } +// +// [Fact] +// public void NullSerializesAsExpectedWithConverters() +// { +// var expected = "null"; +// var value = new BothJsonNullableStringId(null); +// +// var json = SystemTextJsonSerializer.Serialize(value); +// var systemText = SystemTextJsonSerializer.Serialize(value); +// Assert.Equal(expected, systemText); +// Assert.Equal(expected, json); +// } +// +// [Fact] +// public void TypeConverterConvertsNullAsExpected() +// { +// var converter = TypeDescriptor.GetConverter(typeof(NoJsonNullableStringId)); +// var id = converter.ConvertFrom(null); +// Assert.IsType(id); +// Assert.Equal(new NoJsonNullableStringId(null), id); +// +// var reconverted = converter.ConvertTo(id, typeof(string)); +// Assert.Null(reconverted); +// } +// +// #if NET6_0_OR_GREATER +// [Fact] +// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() +// { +// var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreNullableStringId("some name") }; +// using (var context = new ConventionsDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add(original); +// context.SaveChanges(); +// } +// +// using (var context = new ConventionsDbContext(options)) +// { +// var all = context.Entities.ToList(); +// var retrieved = Assert.Single(all); +// Assert.Equal(original.Id, retrieved.Id); +// Assert.Equal(original.Name, retrieved.Name); +// } +// } +// +// public class ConventionsDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public ConventionsDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) +// { +// configurationBuilder +// .Properties() +// .HaveConversion(); +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .ValueGeneratedNever(); +// }); +// } +// } +// #endif +// +// public class TestDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public TestDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Name) +// .HasConversion(new EfCoreNullableStringId.EfCoreValueConverter()) +// .ValueGeneratedNever(); +// }); +// } +// } +// +// public class TestEntity +// { +// public Guid Id { get; set; } +// public EfCoreNullableStringId Name { get; set; } +// } +// +// +// public class EntityWithNullableId +// { +// public NewtonsoftJsonNullableStringId? Id { get; set; } +// } +// } +// } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs index 0cc76b44d..61a9de288 100644 --- a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs @@ -1,364 +1,364 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Threading.Tasks; -using Dapper; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using StronglyTypedIds.IntegrationTests.Types; -using Xunit; -using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; - -namespace StronglyTypedIds.IntegrationTests -{ - public class StringIdTests - { - [Fact] - public async Task ThrowsIfTryToCreateWithNull() - { - await Assert.ThrowsAsync(() => Task.FromResult(new StringId(null))); - } - - [Fact] - public void SameValuesAreEqual() - { - var id = "some-value"; - var foo1 = new StringId(id); - var foo2 = new StringId(id); - - Assert.Equal(foo1, foo2); - } - - [Fact] - public void EmptyValueIsEmpty() - { - Assert.Equal(StringId.Empty.Value, string.Empty); - } - - - [Fact] - public void DifferentValuesAreUnequal() - { - var foo1 = new StringId("value1"); - var foo2 = new StringId("value2"); - - Assert.NotEqual(foo1, foo2); - } - - [Fact] - public void OverloadsWorkCorrectly() - { - var id = "some-value"; - var same1 = new StringId(id); - var same2 = new StringId(id); - var different = new StringId("other value"); - - Assert.True(same1 == same2); - Assert.False(same1 == different); - Assert.False(same1 != same2); - Assert.True(same1 != different); - } - - [Fact] - public void DifferentTypesAreUnequal() - { - var bar = GuidId2.New(); - var foo = new StringId("Value"); - - //Assert.NotEqual(bar, foo); // does not compile - Assert.NotEqual((object)bar, (object)foo); - } - - [Fact] - public void CanSerializeToString_WithNewtonsoftJsonProvider() - { - var foo = new NewtonsoftJsonStringId("123"); - - var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - Assert.Equal(serializedFoo, serializedString); - } - - [Fact] - public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() - { - var entity = new EntityWithNullableId { Id = null }; - - var json = NewtonsoftJsonSerializer.SerializeObject(entity); - var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); - - Assert.NotNull(deserialize); - Assert.Null(deserialize.Id); - } - - [Fact] - public void CanSerializeToString_WithSystemTextJsonProvider() - { - var foo = new SystemTextJsonStringId("123"); - - var serializedFoo = SystemTextJsonSerializer.Serialize(foo); - var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo, serializedString); - } - - [Fact] - public void CanDeserializeFromString_WithNewtonsoftJsonProvider() - { - var value = "123"; - var foo = new NewtonsoftJsonStringId(value); - var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); - - var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanDeserializeFromString_WithSystemTextJsonProvider() - { - var value = "123"; - var foo = new SystemTextJsonStringId(value); - var serializedString = SystemTextJsonSerializer.Serialize(value); - - var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); - - Assert.Equal(foo, deserializedFoo); - } - - [Fact] - public void CanSerializeToString_WithBothJsonConverters() - { - var foo = new BothJsonStringId("123"); - - var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedString1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); - var serializedString2 = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo1, serializedString1); - Assert.Equal(serializedFoo2, serializedString2); - } - - [Fact] - public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() - { - var foo = new NoJsonStringId("123"); - - var serialized = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":\"" + foo.Value + "\"}"; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() - { - var foo = new NoJsonStringId("123"); - - var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); - - var expected = "\"" + foo.Value + "\""; - - Assert.Equal(expected, serialized); - } - - [Fact] - public void WhenNoTypeConverter_SerializesWithValueProperty() - { - var foo = new NoConvertersStringId("123"); - - var newtonsoft = SystemTextJsonSerializer.Serialize(foo); - var systemText = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":\"" + foo.Value + "\"}"; - - Assert.Equal(expected, newtonsoft); - Assert.Equal(expected, systemText); - } - - [Fact] - public void WhenEfCoreValueConverterUsesValueConverter() - { - using var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreStringId("some name") }; - using (var context = new TestDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add(original); - context.SaveChanges(); - } - - using (var context = new TestDbContext(options)) - { - var all = context.Entities.ToList(); - var retrieved = Assert.Single(all); - Assert.Equal(original.Id, retrieved.Id); - Assert.Equal(original.Name, retrieved.Name); - } - } - - [Fact] - public async Task WhenDapperValueConverterUsesValueConverter() - { - using var connection = new SqliteConnection("DataSource=:memory:"); - await connection.OpenAsync(); - - var results = await connection.QueryAsync("SELECT 'this is a value'"); - - var value = Assert.Single(results); - Assert.Equal(value, new DapperStringId("this is a value")); - } - - [Theory] - [InlineData("")] - [InlineData("some value")] - public void TypeConverter_CanConvertToAndFrom(object value) - { - var converter = TypeDescriptor.GetConverter(typeof(NoJsonStringId)); - var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new NoJsonStringId(value?.ToString()), id); - - var reconverted = converter.ConvertTo(id, value.GetType()); - Assert.Equal(value, reconverted); - } - - [Fact] - public void CanCompareDefaults() - { - ComparableStringId original = default; - var other = ComparableStringId.Empty; - - var compare1 = original.CompareTo(other); - var compare2 = other.CompareTo(original); - Assert.Equal(compare1, -compare2); - } - - [Fact] - public void CanEquateDefaults() - { - EquatableStringId original = default; - var other = EquatableStringId.Empty; - - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); - - Assert.Equal(equals1, equals2); - } - - [Fact] - public void ImplementsInterfaces() - { - Assert.IsAssignableFrom>(BothStringId.Empty); - Assert.IsAssignableFrom>(BothStringId.Empty); - - Assert.IsAssignableFrom>(EquatableStringId.Empty); - Assert.IsAssignableFrom>(ComparableStringId.Empty); - -#pragma warning disable 184 - Assert.False(StringId.Empty is IComparable); - Assert.False(StringId.Empty is IEquatable); -#pragma warning restore 184 - } - - -#if NET6_0_OR_GREATER - [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() - { - var connection = new SqliteConnection("DataSource=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreStringId("some name") }; - using (var context = new ConventionsDbContext(options)) - { - context.Database.EnsureCreated(); - context.Entities.Add(original); - context.SaveChanges(); - } - - using (var context = new ConventionsDbContext(options)) - { - var all = context.Entities.ToList(); - var retrieved = Assert.Single(all); - Assert.Equal(original.Id, retrieved.Id); - Assert.Equal(original.Name, retrieved.Name); - } - } - - public class ConventionsDbContext : DbContext - { - public DbSet Entities { get; set; } - - public ConventionsDbContext(DbContextOptions options) : base(options) - { - } - - protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) - { - configurationBuilder - .Properties() - .HaveConversion(); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Id) - .ValueGeneratedNever(); - }); - } - } -#endif - - public class TestDbContext : DbContext - { - public DbSet Entities { get; set; } - - public TestDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder - .Entity(builder => - { - builder - .Property(x => x.Name) - .HasConversion(new EfCoreStringId.EfCoreValueConverter()) - .ValueGeneratedNever(); - }); - } - } - - public class TestEntity - { - public Guid Id { get; set; } - public EfCoreStringId Name { get; set; } - } - - public class EntityWithNullableId - { - public NewtonsoftJsonStringId? Id { get; set; } - } - } -} \ No newline at end of file +// using System; +// using System.ComponentModel; +// using System.Linq; +// using System.Threading.Tasks; +// using Dapper; +// using Microsoft.Data.Sqlite; +// using Microsoft.EntityFrameworkCore; +// using StronglyTypedIds.IntegrationTests.Types; +// using Xunit; +// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; +// +// namespace StronglyTypedIds.IntegrationTests +// { +// public class StringIdTests +// { +// [Fact] +// public async Task ThrowsIfTryToCreateWithNull() +// { +// await Assert.ThrowsAsync(() => Task.FromResult(new StringId(null))); +// } +// +// [Fact] +// public void SameValuesAreEqual() +// { +// var id = "some-value"; +// var foo1 = new StringId(id); +// var foo2 = new StringId(id); +// +// Assert.Equal(foo1, foo2); +// } +// +// [Fact] +// public void EmptyValueIsEmpty() +// { +// Assert.Equal(StringId.Empty.Value, string.Empty); +// } +// +// +// [Fact] +// public void DifferentValuesAreUnequal() +// { +// var foo1 = new StringId("value1"); +// var foo2 = new StringId("value2"); +// +// Assert.NotEqual(foo1, foo2); +// } +// +// [Fact] +// public void OverloadsWorkCorrectly() +// { +// var id = "some-value"; +// var same1 = new StringId(id); +// var same2 = new StringId(id); +// var different = new StringId("other value"); +// +// Assert.True(same1 == same2); +// Assert.False(same1 == different); +// Assert.False(same1 != same2); +// Assert.True(same1 != different); +// } +// +// [Fact] +// public void DifferentTypesAreUnequal() +// { +// var bar = GuidId2.New(); +// var foo = new StringId("Value"); +// +// //Assert.NotEqual(bar, foo); // does not compile +// Assert.NotEqual((object)bar, (object)foo); +// } +// +// [Fact] +// public void CanSerializeToString_WithNewtonsoftJsonProvider() +// { +// var foo = new NewtonsoftJsonStringId("123"); +// +// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); +// +// Assert.Equal(serializedFoo, serializedString); +// } +// +// [Fact] +// public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() +// { +// var entity = new EntityWithNullableId { Id = null }; +// +// var json = NewtonsoftJsonSerializer.SerializeObject(entity); +// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); +// +// Assert.NotNull(deserialize); +// Assert.Null(deserialize.Id); +// } +// +// [Fact] +// public void CanSerializeToString_WithSystemTextJsonProvider() +// { +// var foo = new SystemTextJsonStringId("123"); +// +// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); +// var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); +// +// Assert.Equal(serializedFoo, serializedString); +// } +// +// [Fact] +// public void CanDeserializeFromString_WithNewtonsoftJsonProvider() +// { +// var value = "123"; +// var foo = new NewtonsoftJsonStringId(value); +// var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); +// +// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanDeserializeFromString_WithSystemTextJsonProvider() +// { +// var value = "123"; +// var foo = new SystemTextJsonStringId(value); +// var serializedString = SystemTextJsonSerializer.Serialize(value); +// +// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); +// +// Assert.Equal(foo, deserializedFoo); +// } +// +// [Fact] +// public void CanSerializeToString_WithBothJsonConverters() +// { +// var foo = new BothJsonStringId("123"); +// +// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); +// var serializedString1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); +// +// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); +// var serializedString2 = SystemTextJsonSerializer.Serialize(foo.Value); +// +// Assert.Equal(serializedFoo1, serializedString1); +// Assert.Equal(serializedFoo2, serializedString2); +// } +// +// [Fact] +// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() +// { +// var foo = new NoJsonStringId("123"); +// +// var serialized = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":\"" + foo.Value + "\"}"; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() +// { +// var foo = new NoJsonStringId("123"); +// +// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); +// +// var expected = "\"" + foo.Value + "\""; +// +// Assert.Equal(expected, serialized); +// } +// +// [Fact] +// public void WhenNoTypeConverter_SerializesWithValueProperty() +// { +// var foo = new NoConvertersStringId("123"); +// +// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); +// var systemText = SystemTextJsonSerializer.Serialize(foo); +// +// var expected = "{\"Value\":\"" + foo.Value + "\"}"; +// +// Assert.Equal(expected, newtonsoft); +// Assert.Equal(expected, systemText); +// } +// +// [Fact] +// public void WhenEfCoreValueConverterUsesValueConverter() +// { +// using var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreStringId("some name") }; +// using (var context = new TestDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add(original); +// context.SaveChanges(); +// } +// +// using (var context = new TestDbContext(options)) +// { +// var all = context.Entities.ToList(); +// var retrieved = Assert.Single(all); +// Assert.Equal(original.Id, retrieved.Id); +// Assert.Equal(original.Name, retrieved.Name); +// } +// } +// +// [Fact] +// public async Task WhenDapperValueConverterUsesValueConverter() +// { +// using var connection = new SqliteConnection("DataSource=:memory:"); +// await connection.OpenAsync(); +// +// var results = await connection.QueryAsync("SELECT 'this is a value'"); +// +// var value = Assert.Single(results); +// Assert.Equal(value, new DapperStringId("this is a value")); +// } +// +// [Theory] +// [InlineData("")] +// [InlineData("some value")] +// public void TypeConverter_CanConvertToAndFrom(object value) +// { +// var converter = TypeDescriptor.GetConverter(typeof(NoJsonStringId)); +// var id = converter.ConvertFrom(value); +// Assert.IsType(id); +// Assert.Equal(new NoJsonStringId(value?.ToString()), id); +// +// var reconverted = converter.ConvertTo(id, value.GetType()); +// Assert.Equal(value, reconverted); +// } +// +// [Fact] +// public void CanCompareDefaults() +// { +// ComparableStringId original = default; +// var other = ComparableStringId.Empty; +// +// var compare1 = original.CompareTo(other); +// var compare2 = other.CompareTo(original); +// Assert.Equal(compare1, -compare2); +// } +// +// [Fact] +// public void CanEquateDefaults() +// { +// EquatableStringId original = default; +// var other = EquatableStringId.Empty; +// +// var equals1 = (original as IEquatable).Equals(other); +// var equals2 = (other as IEquatable).Equals(original); +// +// Assert.Equal(equals1, equals2); +// } +// +// [Fact] +// public void ImplementsInterfaces() +// { +// Assert.IsAssignableFrom>(BothStringId.Empty); +// Assert.IsAssignableFrom>(BothStringId.Empty); +// +// Assert.IsAssignableFrom>(EquatableStringId.Empty); +// Assert.IsAssignableFrom>(ComparableStringId.Empty); +// +// #pragma warning disable 184 +// Assert.False(StringId.Empty is IComparable); +// Assert.False(StringId.Empty is IEquatable); +// #pragma warning restore 184 +// } +// +// +// #if NET6_0_OR_GREATER +// [Fact] +// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() +// { +// var connection = new SqliteConnection("DataSource=:memory:"); +// connection.Open(); +// +// var options = new DbContextOptionsBuilder() +// .UseSqlite(connection) +// .Options; +// +// var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreStringId("some name") }; +// using (var context = new ConventionsDbContext(options)) +// { +// context.Database.EnsureCreated(); +// context.Entities.Add(original); +// context.SaveChanges(); +// } +// +// using (var context = new ConventionsDbContext(options)) +// { +// var all = context.Entities.ToList(); +// var retrieved = Assert.Single(all); +// Assert.Equal(original.Id, retrieved.Id); +// Assert.Equal(original.Name, retrieved.Name); +// } +// } +// +// public class ConventionsDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public ConventionsDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) +// { +// configurationBuilder +// .Properties() +// .HaveConversion(); +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Id) +// .ValueGeneratedNever(); +// }); +// } +// } +// #endif +// +// public class TestDbContext : DbContext +// { +// public DbSet Entities { get; set; } +// +// public TestDbContext(DbContextOptions options) : base(options) +// { +// } +// +// protected override void OnModelCreating(ModelBuilder modelBuilder) +// { +// modelBuilder +// .Entity(builder => +// { +// builder +// .Property(x => x.Name) +// .HasConversion(new EfCoreStringId.EfCoreValueConverter()) +// .ValueGeneratedNever(); +// }); +// } +// } +// +// public class TestEntity +// { +// public Guid Id { get; set; } +// public EfCoreStringId Name { get; set; } +// } +// +// public class EntityWithNullableId +// { +// public NewtonsoftJsonStringId? Id { get; set; } +// } +// } +// } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj b/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj index 2800167d3..3e31d5834 100644 --- a/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj +++ b/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1;net6.0;net7.0 + netcoreapp3.1;net5.0;net6.0;net7.0 net48;$(TargetFrameworks) false true diff --git a/test/StronglyTypedIds.IntegrationTests/Types/DefaultId.cs b/test/StronglyTypedIds.IntegrationTests/Types/DefaultId.cs deleted file mode 100644 index cbe84fe1d..000000000 --- a/test/StronglyTypedIds.IntegrationTests/Types/DefaultId.cs +++ /dev/null @@ -1,41 +0,0 @@ -using StronglyTypedIds; -[assembly: StronglyTypedIdDefaults(converters: StronglyTypedIdConverter.None, implementations: StronglyTypedIdImplementations.None)] - -namespace StronglyTypedIds.IntegrationTests.Types -{ - [StronglyTypedId] - partial struct DefaultId1 { } - - [StronglyTypedId] - public partial struct DefaultId2 { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.None)] - public partial struct NoConverterDefaultId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.TypeConverter)] - public partial struct NoJsonDefaultId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson)] - public partial struct NewtonsoftJsonDefaultId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.TypeConverter | StronglyTypedIdConverter.SystemTextJson)] - public partial struct SystemTextJsonDefaultId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson | StronglyTypedIdConverter.SystemTextJson)] - public partial struct BothJsonDefaultId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.EfCoreValueConverter)] - public partial struct EfCoreDefaultId { } - - public partial class SomeType where T : new() - { - public partial record NestedType - { - public partial struct MoreNesting - { - [StronglyTypedId] - public partial struct VeryNestedId {} - } - } - } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/Types/GuidId.cs b/test/StronglyTypedIds.IntegrationTests/Types/GuidId.cs deleted file mode 100644 index 9ad651d72..000000000 --- a/test/StronglyTypedIds.IntegrationTests/Types/GuidId.cs +++ /dev/null @@ -1,40 +0,0 @@ -using StronglyTypedIds; - -namespace StronglyTypedIds.IntegrationTests.Types -{ - [StronglyTypedId] - partial struct GuidId1 { } - - [StronglyTypedId] - public partial struct GuidId2 { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.None)] - public partial struct NoConverterGuidId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.TypeConverter)] - public partial struct NoJsonGuidId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson)] - public partial struct NewtonsoftJsonGuidId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.TypeConverter | StronglyTypedIdConverter.SystemTextJson)] - public partial struct SystemTextJsonGuidId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson | StronglyTypedIdConverter.SystemTextJson)] - public partial struct BothJsonGuidId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.EfCoreValueConverter)] - public partial struct EfCoreGuidId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.DapperTypeHandler)] - public partial struct DapperGuidId { } - - [StronglyTypedId(implementations: StronglyTypedIdImplementations.IEquatable | StronglyTypedIdImplementations.IComparable)] - public partial struct BothGuidId { } - - [StronglyTypedId(implementations: StronglyTypedIdImplementations.IEquatable)] - public partial struct EquatableGuidId { } - - [StronglyTypedId(implementations: StronglyTypedIdImplementations.IComparable)] - public partial struct ComparableGuidId { } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/Types/IntId.cs b/test/StronglyTypedIds.IntegrationTests/Types/IntId.cs deleted file mode 100644 index 15316b98a..000000000 --- a/test/StronglyTypedIds.IntegrationTests/Types/IntId.cs +++ /dev/null @@ -1,37 +0,0 @@ -using StronglyTypedIds; - -namespace StronglyTypedIds.IntegrationTests.Types -{ - [StronglyTypedId(backingType: StronglyTypedIdBackingType.Int)] - partial struct IntId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.None, backingType: StronglyTypedIdBackingType.Int)] - public partial struct NoConverterIntId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.TypeConverter, backingType: StronglyTypedIdBackingType.Int)] - public partial struct NoJsonIntId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson, backingType: StronglyTypedIdBackingType.Int)] - public partial struct NewtonsoftJsonIntId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.SystemTextJson, backingType: StronglyTypedIdBackingType.Int)] - public partial struct SystemTextJsonIntId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson | StronglyTypedIdConverter.SystemTextJson, backingType: StronglyTypedIdBackingType.Int)] - public partial struct BothJsonIntId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.EfCoreValueConverter, backingType: StronglyTypedIdBackingType.Int)] - public partial struct EfCoreIntId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.DapperTypeHandler, backingType: StronglyTypedIdBackingType.Int)] - public partial struct DapperIntId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.Int, implementations: StronglyTypedIdImplementations.IEquatable | StronglyTypedIdImplementations.IComparable)] - public partial struct BothIntId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.Int, implementations: StronglyTypedIdImplementations.IEquatable)] - public partial struct EquatableIntId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.Int, implementations: StronglyTypedIdImplementations.IComparable)] - public partial struct ComparableIntId { } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/Types/LongId.cs b/test/StronglyTypedIds.IntegrationTests/Types/LongId.cs deleted file mode 100644 index 5a1081bb8..000000000 --- a/test/StronglyTypedIds.IntegrationTests/Types/LongId.cs +++ /dev/null @@ -1,37 +0,0 @@ -using StronglyTypedIds; - -namespace StronglyTypedIds.IntegrationTests.Types -{ - [StronglyTypedId(backingType: StronglyTypedIdBackingType.Long)] - partial struct LongId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.None, backingType: StronglyTypedIdBackingType.Long)] - public partial struct NoConverterLongId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.TypeConverter, backingType: StronglyTypedIdBackingType.Long)] - public partial struct NoJsonLongId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson, backingType: StronglyTypedIdBackingType.Long)] - public partial struct NewtonsoftJsonLongId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.SystemTextJson, backingType: StronglyTypedIdBackingType.Long)] - public partial struct SystemTextJsonLongId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson | StronglyTypedIdConverter.SystemTextJson, backingType: StronglyTypedIdBackingType.Long)] - public partial struct BothJsonLongId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.EfCoreValueConverter, backingType: StronglyTypedIdBackingType.Long)] - public partial struct EfCoreLongId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.DapperTypeHandler, backingType: StronglyTypedIdBackingType.Long)] - public partial struct DapperLongId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.Long, implementations: StronglyTypedIdImplementations.IEquatable | StronglyTypedIdImplementations.IComparable)] - public partial struct BothLongId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.Long, implementations: StronglyTypedIdImplementations.IEquatable)] - public partial struct EquatableLongId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.Long, implementations: StronglyTypedIdImplementations.IComparable)] - public partial struct ComparableLongId { } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/Types/NewIdId.cs b/test/StronglyTypedIds.IntegrationTests/Types/NewIdId.cs deleted file mode 100644 index 0be4ce4c9..000000000 --- a/test/StronglyTypedIds.IntegrationTests/Types/NewIdId.cs +++ /dev/null @@ -1,40 +0,0 @@ -using StronglyTypedIds; - -namespace StronglyTypedIds.IntegrationTests.Types -{ - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId)] - partial struct NewIdId1 { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId)] - public partial struct NewIdId2 { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, converters: StronglyTypedIdConverter.None)] - public partial struct NoConverterNewIdId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, converters: StronglyTypedIdConverter.TypeConverter)] - public partial struct NoJsonNewIdId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, converters: StronglyTypedIdConverter.NewtonsoftJson)] - public partial struct NewtonsoftJsonNewIdId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, converters: StronglyTypedIdConverter.TypeConverter | StronglyTypedIdConverter.SystemTextJson)] - public partial struct SystemTextJsonNewIdId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, converters: StronglyTypedIdConverter.NewtonsoftJson | StronglyTypedIdConverter.SystemTextJson)] - public partial struct BothJsonNewIdId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, converters: StronglyTypedIdConverter.EfCoreValueConverter)] - public partial struct EfCoreNewIdId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, converters: StronglyTypedIdConverter.DapperTypeHandler)] - public partial struct DapperNewIdId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, implementations: StronglyTypedIdImplementations.IEquatable | StronglyTypedIdImplementations.IComparable)] - public partial struct BothNewIdId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, implementations: StronglyTypedIdImplementations.IEquatable)] - public partial struct EquatableNewIdId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.MassTransitNewId, implementations: StronglyTypedIdImplementations.IComparable)] - public partial struct ComparableNewIdId { } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/Types/NullableStringId.cs b/test/StronglyTypedIds.IntegrationTests/Types/NullableStringId.cs deleted file mode 100644 index d51e901a1..000000000 --- a/test/StronglyTypedIds.IntegrationTests/Types/NullableStringId.cs +++ /dev/null @@ -1,37 +0,0 @@ -using StronglyTypedIds; - -namespace StronglyTypedIds.IntegrationTests.Types -{ - [StronglyTypedId(backingType: StronglyTypedIdBackingType.NullableString)] - partial struct NullableStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.None, backingType: StronglyTypedIdBackingType.NullableString)] - public partial struct NoConvertersNullableStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.TypeConverter, backingType: StronglyTypedIdBackingType.NullableString)] - public partial struct NoJsonNullableStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson, backingType: StronglyTypedIdBackingType.NullableString)] - public partial struct NewtonsoftJsonNullableStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.SystemTextJson, backingType: StronglyTypedIdBackingType.NullableString)] - public partial struct SystemTextJsonNullableStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson | StronglyTypedIdConverter.SystemTextJson, backingType: StronglyTypedIdBackingType.NullableString)] - public partial struct BothJsonNullableStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.EfCoreValueConverter, backingType: StronglyTypedIdBackingType.NullableString)] - public partial struct EfCoreNullableStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.DapperTypeHandler, backingType: StronglyTypedIdBackingType.NullableString)] - public partial struct DapperNullableStringId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.NullableString, implementations: StronglyTypedIdImplementations.IEquatable | StronglyTypedIdImplementations.IComparable)] - public partial struct BothNullableStringId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.NullableString, implementations: StronglyTypedIdImplementations.IEquatable)] - public partial struct EquatableNullableStringId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.NullableString, implementations: StronglyTypedIdImplementations.IComparable)] - public partial struct ComparableNullableStringId { } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/Types/StringId.cs b/test/StronglyTypedIds.IntegrationTests/Types/StringId.cs deleted file mode 100644 index 5e7cdfa57..000000000 --- a/test/StronglyTypedIds.IntegrationTests/Types/StringId.cs +++ /dev/null @@ -1,37 +0,0 @@ -using StronglyTypedIds; - -namespace StronglyTypedIds.IntegrationTests.Types -{ - [StronglyTypedId(backingType: StronglyTypedIdBackingType.String)] - partial struct StringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.None, backingType: StronglyTypedIdBackingType.String)] - public partial struct NoConvertersStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.TypeConverter, backingType: StronglyTypedIdBackingType.String)] - public partial struct NoJsonStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson, backingType: StronglyTypedIdBackingType.String)] - public partial struct NewtonsoftJsonStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.SystemTextJson, backingType: StronglyTypedIdBackingType.String)] - public partial struct SystemTextJsonStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.NewtonsoftJson | StronglyTypedIdConverter.SystemTextJson, backingType: StronglyTypedIdBackingType.String)] - public partial struct BothJsonStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.EfCoreValueConverter, backingType: StronglyTypedIdBackingType.String)] - public partial struct EfCoreStringId { } - - [StronglyTypedId(converters: StronglyTypedIdConverter.DapperTypeHandler, backingType: StronglyTypedIdBackingType.String)] - public partial struct DapperStringId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.String, implementations: StronglyTypedIdImplementations.IEquatable | StronglyTypedIdImplementations.IComparable)] - public partial struct BothStringId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.String, implementations: StronglyTypedIdImplementations.IEquatable)] - public partial struct EquatableStringId { } - - [StronglyTypedId(backingType: StronglyTypedIdBackingType.String, implementations: StronglyTypedIdImplementations.IComparable)] - public partial struct ComparableStringId { } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/EnumHelper.cs b/test/StronglyTypedIds.Tests/EnumHelper.cs deleted file mode 100644 index ea74cd267..000000000 --- a/test/StronglyTypedIds.Tests/EnumHelper.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace StronglyTypedIds.Tests -{ - public class EnumHelper - { - public static IEnumerable AllBackingTypes(bool includeDefault = true) - => Enum.GetValues(typeof(StronglyTypedIdBackingType)) - .Cast() - .Where(value => value != StronglyTypedIdBackingType.Default || includeDefault); - - public static IEnumerable AllConverters(bool includeDefault = true) - => Enum.GetValues(typeof(StronglyTypedIdConverter)) - .Cast() - .Where(value => value != StronglyTypedIdConverter.Default || includeDefault); - - public static IEnumerable AllImplementations(bool includeDefault = true) - => Enum.GetValues(typeof(StronglyTypedIdImplementations)) - .Cast() - .Where(value => value != StronglyTypedIdImplementations.Default || includeDefault); - - public static IEnumerable AllConverterCombinations(bool includeDefault = true, bool includeNone = true) - { - // get highest value - var highestValue = Enum.GetValues(typeof(StronglyTypedIdConverter)) - .Cast() - .Max(); - - var upperBound = highestValue * 2; - for (var i = 0; i < upperBound; i++) - { - var converter = (StronglyTypedIdConverter)i; - if (converter.IsSet(StronglyTypedIdConverter.Default) && !includeDefault - || converter == StronglyTypedIdConverter.None && !includeNone) - { - continue; - } - - yield return converter; - } - } - - public static IEnumerable AllImplementationCombinations(bool includeDefault = true, bool includeNone = true) - { - // get highest value - var highestValue = Enum.GetValues(typeof(StronglyTypedIdImplementations)) - .Cast() - .Max(); - - var upperBound = highestValue * 2; - for (var i = 0; i < upperBound; i++) - { - var implementations = (StronglyTypedIdImplementations)i; - if (implementations.IsSet(StronglyTypedIdImplementations.Default) && !includeDefault - || implementations == StronglyTypedIdImplementations.None && !includeNone) - { - continue; - } - - yield return implementations; - } - } - } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/EqualityTests.cs b/test/StronglyTypedIds.Tests/EqualityTests.cs index 3270b0a52..f7db52c62 100644 --- a/test/StronglyTypedIds.Tests/EqualityTests.cs +++ b/test/StronglyTypedIds.Tests/EqualityTests.cs @@ -33,20 +33,6 @@ public void ParentClassWithParentHasExpectedEqualityBehaviour() ParentClass GetParentClass() => new("struct", "TestName", "where T : class", new ParentClass("class", "b", "", null)); } - [Fact] - public void StronglyTypedIdConfigurationHasExpectedEqualityBehaviour() - { - var id1 = GetId(); - var id2 = GetId(); - Assert.True(id1.Equals(id2)); - Assert.Equal(id1, id2); - } - - private static StronglyTypedIdConfiguration GetId() - { - return new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default); - } - [Fact] public void StructToGenerateHasExpectedEqualityBehaviour() { @@ -61,7 +47,7 @@ StructToGenerate GetStruct() => new( name: "MyStruct", nameSpace: "MyNamespace", - config: new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default), + templateName: "Guid", parent: null); } @@ -80,7 +66,7 @@ StructToGenerate GetStruct() return new StructToGenerate( name: "MyStruct", nameSpace: "MyNamespace", - config: new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default), + templateName: "Guid", parent: new ParentClass("class", "b", "", null)); } } @@ -100,7 +86,7 @@ public void ResultWithoutDiagnosticHasExpectedEqualityBehaviour() var instance = new StructToGenerate( name: "MyStruct", nameSpace: "MyNamespace", - config: new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default), + templateName: "Guid", parent: new ParentClass("class", "b", "", null)); return new Result<(StructToGenerate, bool)>((instance, true), new EquatableArray()); @@ -122,7 +108,7 @@ public void ResultWithDiagnosticHasExpectedEqualityBehaviour() var instance = new StructToGenerate( name: "MyStruct", nameSpace: "MyNamespace", - config: new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default), + templateName: "Guid", parent: new ParentClass("class", "b", "", null)); var diagnostics = new DiagnosticInfo(new DiagnosticDescriptor( InvalidBackingTypeDiagnostic.Id, InvalidBackingTypeDiagnostic.Title, InvalidBackingTypeDiagnostic.Message, category: Constants.Usage, diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt index 58a2c4794..1407dd75d 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt @@ -9,6 +9,7 @@ #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; @@ -18,7 +19,7 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { @@ -33,6 +34,7 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// If not set, uses , which defaults to /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -43,6 +45,34 @@ namespace StronglyTypedIds Implementations = implementations; } + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + /// /// The to use to store the strongly-typed ID value /// @@ -57,6 +87,16 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdBackingType.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdBackingType.verified.txt index 4ea1be319..921a10fce 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdBackingType.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdBackingType.verified.txt @@ -9,6 +9,7 @@ #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdConverter.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdConverter.verified.txt index 32b324616..d3f7ebf63 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdConverter.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdConverter.verified.txt @@ -9,6 +9,7 @@ #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt index 3df9e2e31..35133ef98 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt @@ -9,6 +9,7 @@ #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; @@ -16,7 +17,8 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] @@ -31,6 +33,7 @@ namespace StronglyTypedIds /// Defaults to and /// Interfaces and patterns the strongly typed id should implement /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdDefaultsAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -41,6 +44,27 @@ namespace StronglyTypedIds Implementations = implementations; } + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + /// /// The default to use to store the strongly-typed ID values. /// @@ -55,6 +79,16 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdImplementations.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdImplementations.verified.txt index 76835ffec..92b322504 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdImplementations.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdImplementations.verified.txt @@ -9,6 +9,7 @@ #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index e397007be..c23dd3c69 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -7,7 +7,7 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { @@ -22,6 +22,7 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// If not set, uses , which defaults to /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -32,6 +33,34 @@ namespace StronglyTypedIds Implementations = implementations; } + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + /// /// The to use to store the strongly-typed ID value /// @@ -46,6 +75,16 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -56,7 +95,8 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] @@ -71,6 +111,7 @@ namespace StronglyTypedIds /// Defaults to and /// Interfaces and patterns the strongly typed id should implement /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdDefaultsAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -82,137 +123,50 @@ namespace StronglyTypedIds } /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string + /// Set the default template to use for strongly typed IDs /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } /// - /// Creates an EF Core Value Converter for extracting the primitive value + /// Set the default template to use for strongly typed IDs /// - EfCoreValueConverter = 16, + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } /// - /// Creates a Dapper TypeHandler for converting to and from the type + /// The default to use to store the strongly-typed ID values. /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc + public StronglyTypedIdBackingType BackingType { get; } /// - /// Don't implement any additional members for the strongly typed ID + /// The default converters to create for serializing/deserializing strongly-typed ID values. /// - None = 0, + public StronglyTypedIdConverter Converters { get; } /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and + /// Interfaces and patterns the strongly typed id should implement /// - Default = 1, + public StronglyTypedIdImplementations Implementations { get; } - // ReSharper disable once InconsistentNaming /// - /// Implement the interface + /// The default template to use to generate the strongly-typed ID value. /// - IEquatable = 2, + public string? TemplateName { get; } - // ReSharper disable once InconsistentNaming /// - /// Implement the interface + /// The default template to use to generate the strongly-typed ID value. /// - IComparable = 4, + public Template? Template { get; } } } #endif @@ -227,19 +181,19 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(TypeConverter))] + readonly partial struct MyId : global::System.IComparable, global::System.IEquatable { - public System.Guid Value { get; } + public global::System.Guid Value { get; } - public MyId(System.Guid value) + public MyId(global::System.Guid value) { Value = value; } - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); public bool Equals(MyId other) => this.Value.Equals(other.Value); public override bool Equals(object obj) @@ -253,35 +207,36 @@ namespace StronglyTypedIds public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + public override object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value) { return value switch { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value; } @@ -295,24 +250,4 @@ namespace StronglyTypedIds return base.ConvertTo(context, culture, value, destinationType); } } - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index 0b021b89a..416efd070 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -7,7 +7,7 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { @@ -22,6 +22,7 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// If not set, uses , which defaults to /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -32,6 +33,34 @@ namespace StronglyTypedIds Implementations = implementations; } + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + /// /// The to use to store the strongly-typed ID value /// @@ -46,6 +75,16 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -56,7 +95,8 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] @@ -71,6 +111,7 @@ namespace StronglyTypedIds /// Defaults to and /// Interfaces and patterns the strongly typed id should implement /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdDefaultsAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -82,137 +123,50 @@ namespace StronglyTypedIds } /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string + /// Set the default template to use for strongly typed IDs /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } /// - /// Creates an EF Core Value Converter for extracting the primitive value + /// Set the default template to use for strongly typed IDs /// - EfCoreValueConverter = 16, + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } /// - /// Creates a Dapper TypeHandler for converting to and from the type + /// The default to use to store the strongly-typed ID values. /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc + public StronglyTypedIdBackingType BackingType { get; } /// - /// Don't implement any additional members for the strongly typed ID + /// The default converters to create for serializing/deserializing strongly-typed ID values. /// - None = 0, + public StronglyTypedIdConverter Converters { get; } /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and + /// Interfaces and patterns the strongly typed id should implement /// - Default = 1, + public StronglyTypedIdImplementations Implementations { get; } - // ReSharper disable once InconsistentNaming /// - /// Implement the interface + /// The default template to use to generate the strongly-typed ID value. /// - IEquatable = 2, + public string? TemplateName { get; } - // ReSharper disable once InconsistentNaming /// - /// Implement the interface + /// The default template to use to generate the strongly-typed ID value. /// - IComparable = 4, + public Template? Template { get; } } } #endif @@ -227,21 +181,21 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable namespace SomeNamespace { - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable + [global::System.ComponentModel.TypeConverter(typeof(TypeConverter))] + readonly partial struct MyId : global::System.IComparable, global::System.IEquatable { - public System.Guid Value { get; } + public global::System.Guid Value { get; } - public MyId(System.Guid value) + public MyId(global::System.Guid value) { Value = value; } - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); public bool Equals(MyId other) => this.Value.Equals(other.Value); public override bool Equals(object obj) @@ -255,35 +209,36 @@ namespace SomeNamespace public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + public override object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value) { return value switch { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value; } @@ -297,25 +252,5 @@ namespace SomeNamespace return base.ConvertTo(context, culture, value, destinationType); } } - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt new file mode 100644 index 000000000..8e602474f --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt @@ -0,0 +1,524 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_OR_GREATER + global::System.IParsable, global::System.ISpanParsable +#endif +#endif + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index 0b021b89a..416efd070 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -7,7 +7,7 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { @@ -22,6 +22,7 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// If not set, uses , which defaults to /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -32,6 +33,34 @@ namespace StronglyTypedIds Implementations = implementations; } + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + /// /// The to use to store the strongly-typed ID value /// @@ -46,6 +75,16 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -56,7 +95,8 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] @@ -71,6 +111,7 @@ namespace StronglyTypedIds /// Defaults to and /// Interfaces and patterns the strongly typed id should implement /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdDefaultsAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -82,137 +123,50 @@ namespace StronglyTypedIds } /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string + /// Set the default template to use for strongly typed IDs /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } /// - /// Creates an EF Core Value Converter for extracting the primitive value + /// Set the default template to use for strongly typed IDs /// - EfCoreValueConverter = 16, + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } /// - /// Creates a Dapper TypeHandler for converting to and from the type + /// The default to use to store the strongly-typed ID values. /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc + public StronglyTypedIdBackingType BackingType { get; } /// - /// Don't implement any additional members for the strongly typed ID + /// The default converters to create for serializing/deserializing strongly-typed ID values. /// - None = 0, + public StronglyTypedIdConverter Converters { get; } /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and + /// Interfaces and patterns the strongly typed id should implement /// - Default = 1, + public StronglyTypedIdImplementations Implementations { get; } - // ReSharper disable once InconsistentNaming /// - /// Implement the interface + /// The default template to use to generate the strongly-typed ID value. /// - IEquatable = 2, + public string? TemplateName { get; } - // ReSharper disable once InconsistentNaming /// - /// Implement the interface + /// The default template to use to generate the strongly-typed ID value. /// - IComparable = 4, + public Template? Template { get; } } } #endif @@ -227,21 +181,21 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable namespace SomeNamespace { - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable + [global::System.ComponentModel.TypeConverter(typeof(TypeConverter))] + readonly partial struct MyId : global::System.IComparable, global::System.IEquatable { - public System.Guid Value { get; } + public global::System.Guid Value { get; } - public MyId(System.Guid value) + public MyId(global::System.Guid value) { Value = value; } - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); public bool Equals(MyId other) => this.Value.Equals(other.Value); public override bool Equals(object obj) @@ -255,35 +209,36 @@ namespace SomeNamespace public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + public override object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value) { return value switch { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value; } @@ -297,25 +252,5 @@ namespace SomeNamespace return base.ConvertTo(context, culture, value, destinationType); } } - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 7e73d73fe..4b42d88ad 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -12,40 +12,29 @@ namespace StronglyTypedIds internal sealed class StronglyTypedIdAttribute : Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value + /// Make the struct a strongly typed ID, using the default settings /// - public StronglyTypedIdConverter Converters { get; } + public StronglyTypedIdAttribute() + { + TemplateName = null; + } /// - /// Interfaces and patterns the strongly typed id should implement + /// The to use to store the strongly-typed ID value. /// - public StronglyTypedIdImplementations Implementations { get; } + public string? TemplateName { get; } } } #endif @@ -62,157 +51,25 @@ namespace StronglyTypedIds [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdDefaultsAttribute : Attribute { + /// + /// The to use to store the strongly-typed ID value + /// /// /// Set the default values used for strongly typed ids /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface + /// The to use to store the strongly-typed ID value /// - IComparable = 4, + public string TemplateName { get; } } } #endif @@ -229,7 +86,6 @@ namespace StronglyTypedIds namespace MyContracts.V1 { - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] readonly partial struct MyId : System.IComparable, System.IEquatable { @@ -255,6 +111,7 @@ namespace MyContracts.V1 public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); class MyIdTypeConverter : System.ComponentModel.TypeConverter @@ -297,26 +154,6 @@ namespace MyContracts.V1 return base.ConvertTo(context, culture, value, destinationType); } } - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } } } @@ -333,7 +170,6 @@ namespace MyContracts.V1 namespace MyContracts.V2 { - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] readonly partial struct MyId : System.IComparable, System.IEquatable { @@ -359,6 +195,7 @@ namespace MyContracts.V2 public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); class MyIdTypeConverter : System.ComponentModel.TypeConverter @@ -401,25 +238,5 @@ namespace MyContracts.V2 return base.ConvertTo(context, culture, value, destinationType); } } - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index c259d55ac..2d2fb86fc 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -12,40 +12,29 @@ namespace StronglyTypedIds internal sealed class StronglyTypedIdAttribute : Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value + /// Make the struct a strongly typed ID, using the default settings /// - public StronglyTypedIdConverter Converters { get; } + public StronglyTypedIdAttribute() + { + TemplateName = null; + } /// - /// Interfaces and patterns the strongly typed id should implement + /// The to use to store the strongly-typed ID value. /// - public StronglyTypedIdImplementations Implementations { get; } + public string? TemplateName { get; } } } #endif @@ -62,157 +51,25 @@ namespace StronglyTypedIds [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdDefaultsAttribute : Attribute { + /// + /// The to use to store the strongly-typed ID value + /// /// /// Set the default values used for strongly typed ids /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface + /// The to use to store the strongly-typed ID value /// - IComparable = 4, + public string TemplateName { get; } } } #endif @@ -231,7 +88,6 @@ namespace SomeNamespace { partial class ParentClass { - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] readonly partial struct MyId : System.IComparable, System.IEquatable { @@ -257,6 +113,7 @@ namespace SomeNamespace public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); class MyIdTypeConverter : System.ComponentModel.TypeConverter @@ -299,26 +156,6 @@ namespace SomeNamespace return base.ConvertTo(context, culture, value, destinationType); } } - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } } } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index ebcdb6716..37acd1a1a 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -12,40 +12,29 @@ namespace StronglyTypedIds internal sealed class StronglyTypedIdAttribute : Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value + /// Make the struct a strongly typed ID, using the default settings /// - public StronglyTypedIdConverter Converters { get; } + public StronglyTypedIdAttribute() + { + TemplateName = null; + } /// - /// Interfaces and patterns the strongly typed id should implement + /// The to use to store the strongly-typed ID value. /// - public StronglyTypedIdImplementations Implementations { get; } + public string? TemplateName { get; } } } #endif @@ -62,157 +51,25 @@ namespace StronglyTypedIds [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdDefaultsAttribute : Attribute { + /// + /// The to use to store the strongly-typed ID value + /// /// /// Set the default values used for strongly typed ids /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface + /// The to use to store the strongly-typed ID value /// - IComparable = 4, + public string TemplateName { get; } } } #endif @@ -235,7 +92,6 @@ namespace SomeNamespace { partial struct InnerStruct { - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] readonly partial struct MyId : System.IComparable, System.IEquatable { @@ -261,6 +117,7 @@ namespace SomeNamespace public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); class MyIdTypeConverter : System.ComponentModel.TypeConverter @@ -303,26 +160,6 @@ namespace SomeNamespace return base.ConvertTo(context, culture, value, destinationType); } } - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } } } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt index 02e7314d4..e7bc0d334 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt @@ -12,40 +12,29 @@ namespace StronglyTypedIds internal sealed class StronglyTypedIdAttribute : Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value + /// Make the struct a strongly typed ID, using the default settings /// - public StronglyTypedIdConverter Converters { get; } + public StronglyTypedIdAttribute() + { + TemplateName = null; + } /// - /// Interfaces and patterns the strongly typed id should implement + /// The to use to store the strongly-typed ID value. /// - public StronglyTypedIdImplementations Implementations { get; } + public string? TemplateName { get; } } } #endif @@ -62,157 +51,25 @@ namespace StronglyTypedIds [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdDefaultsAttribute : Attribute { + /// + /// The to use to store the strongly-typed ID value + /// /// /// Set the default values used for strongly typed ids /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface + /// The to use to store the strongly-typed ID value /// - IComparable = 4, + public string TemplateName { get; } } } #endif @@ -227,6 +84,7 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented + [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] readonly partial struct MyId : System.IComparable, System.IEquatable { public int Value { get; } @@ -250,5 +108,47 @@ namespace StronglyTypedIds public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + return value switch + { + int intValue => new MyId(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt index 02e7314d4..e7bc0d334 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt @@ -12,40 +12,29 @@ namespace StronglyTypedIds internal sealed class StronglyTypedIdAttribute : Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value + /// Make the struct a strongly typed ID, using the default settings /// - public StronglyTypedIdConverter Converters { get; } + public StronglyTypedIdAttribute() + { + TemplateName = null; + } /// - /// Interfaces and patterns the strongly typed id should implement + /// The to use to store the strongly-typed ID value. /// - public StronglyTypedIdImplementations Implementations { get; } + public string? TemplateName { get; } } } #endif @@ -62,157 +51,25 @@ namespace StronglyTypedIds [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdDefaultsAttribute : Attribute { + /// + /// The to use to store the strongly-typed ID value + /// /// /// Set the default values used for strongly typed ids /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + TemplateName = templateName; } /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface + /// The to use to store the strongly-typed ID value /// - IComparable = 4, + public string TemplateName { get; } } } #endif @@ -227,6 +84,7 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented + [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] readonly partial struct MyId : System.IComparable, System.IEquatable { public int Value { get; } @@ -250,5 +108,47 @@ namespace StronglyTypedIds public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + return value switch + { + int intValue => new MyId(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } } diff --git a/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs b/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs index f831c5de8..277b2dc32 100644 --- a/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs +++ b/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs @@ -1,172 +1,172 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using VerifyXunit; -using Xunit; - -namespace StronglyTypedIds.Tests -{ - [UsesVerify] - public class SourceGenerationHelperSnapshotTests - { - private const string IdNamespace = "Some.Namespace"; - - [Theory] - [InlineData(null)] - [InlineData("")] - public void ThrowsWhenClassNameIsNullOrEmpty(string idName) - { - Assert.Throws(() => SourceGenerationHelper.CreateId( - idName: idName, - idNamespace: IdNamespace, - parentClass: null, - converters: StronglyTypedIdConverter.None, - backingType: StronglyTypedIdBackingType.Guid, - implementations: StronglyTypedIdImplementations.None - )); - } - - [Fact] - public void ThrowsWhenDefaultConverterIsUsed() - { - Assert.Throws(() => SourceGenerationHelper.CreateId( - idName: "MyTestId", - idNamespace: IdNamespace, - parentClass: null, - converters: StronglyTypedIdConverter.Default, - backingType: StronglyTypedIdBackingType.Guid, - implementations: StronglyTypedIdImplementations.None - )); - } - - [Fact] - public void ThrowsWhenDefaultBackingTypeIsUsed() - { - Assert.Throws(() => SourceGenerationHelper.CreateId( - idName: "MyTestId", - idNamespace: IdNamespace, - parentClass: null, - converters: StronglyTypedIdConverter.None, - backingType: StronglyTypedIdBackingType.Default, - implementations: StronglyTypedIdImplementations.None - )); - } - - [Fact] - public void ThrowsWhenDefaultImplementationsIsUsed() - { - Assert.Throws(() => SourceGenerationHelper.CreateId( - idName: "MyTestId", - idNamespace: IdNamespace, - parentClass: null, - converters: StronglyTypedIdConverter.None, - backingType: StronglyTypedIdBackingType.Guid, - implementations: StronglyTypedIdImplementations.Default - )); - } - - [Theory] - [MemberData(nameof(Parameters))] - public Task GeneratesIdCorrectly( - StronglyTypedIdBackingType type, - StronglyTypedIdConverter c, - StronglyTypedIdImplementations i) - { - const string idName = "MyTestId"; - var result = SourceGenerationHelper.CreateId( - idName: idName, - idNamespace: "", - parentClass: null, - converters: c, - backingType: type, - implementations: i - ); - - return Verifier.Verify(result) - .UseDirectory("Snapshots") - .UseParameters(type, c, i); - } - - [Theory] - [MemberData(nameof(BackingTypes))] - public Task GeneratesFullIdCorrectly(StronglyTypedIdBackingType type) - { - // combine them all - var combinedConverter = EnumHelper.AllConverters(includeDefault: false) - .Aggregate(StronglyTypedIdConverter.None, (prev, current) => prev | current); - - // combine them all - var combinedImplementation = EnumHelper.AllImplementations(includeDefault: false) - .Aggregate(StronglyTypedIdImplementations.None, (prev, current) => prev | current); - - const string idName = "MyTestId"; - - var result = SourceGenerationHelper.CreateId( - idName: idName, - idNamespace: "", - parentClass: null, - converters: combinedConverter, - backingType: type, - implementations: combinedImplementation - ); - - return Verifier.Verify(result) - .UseDirectory("Snapshots") - .UseParameters(type); - } - - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(2)] - public Task GeneratesIdWithNestedClassCorrectly(int nestedClassCount) - { - var parent = new ParentClass("record", "InnerMost", string.Empty, child: null); - for (int i = 0; i < nestedClassCount; i++) - { - parent = new ParentClass("class", "OuterLayer" + i, string.Empty, parent); - } - - var result = SourceGenerationHelper.CreateId( - idName: "MyTestId", - idNamespace: "MyTestNamespace", - parentClass: parent, - converters: StronglyTypedIdConverter.SystemTextJson, - backingType: StronglyTypedIdBackingType.Guid, - implementations: StronglyTypedIdImplementations.None - ); - - return Verifier.Verify(result) - .UseDirectory("Snapshots") - .UseParameters(nestedClassCount); - } - - public static IEnumerable BackingTypes() - => EnumHelper.AllBackingTypes(includeDefault: false) - .Select(x => new object[] { x }); - - public static IEnumerable Parameters() - { - foreach (var backingType in EnumHelper.AllBackingTypes(includeDefault: false)) - { - // All individual convert types - foreach (var converter in EnumHelper.AllConverters(includeDefault: false)) - { - yield return new object[] { backingType, converter, StronglyTypedIdImplementations.None }; - } - - // All individual implementations - foreach (var implementation in EnumHelper.AllImplementations(includeDefault: false)) - { - if (implementation is StronglyTypedIdImplementations.None) - { - // We've already covered this one in the previous loop - continue; - } - yield return new object[] { backingType, StronglyTypedIdConverter.None, implementation }; - } - } - } - } -} \ No newline at end of file +// using System; +// using System.Collections.Generic; +// using System.Linq; +// using System.Threading.Tasks; +// using VerifyXunit; +// using Xunit; +// +// namespace StronglyTypedIds.Tests +// { +// [UsesVerify] +// public class SourceGenerationHelperSnapshotTests +// { +// private const string IdNamespace = "Some.Namespace"; +// +// [Theory] +// [InlineData(null)] +// [InlineData("")] +// public void ThrowsWhenClassNameIsNullOrEmpty(string idName) +// { +// Assert.Throws(() => SourceGenerationHelper.CreateId( +// idName: idName, +// idNamespace: IdNamespace, +// parentClass: null, +// converters: StronglyTypedIdConverter.None, +// backingType: StronglyTypedIdBackingType.Guid, +// implementations: StronglyTypedIdImplementations.None +// )); +// } +// +// [Fact] +// public void ThrowsWhenDefaultConverterIsUsed() +// { +// Assert.Throws(() => SourceGenerationHelper.CreateId( +// idName: "MyTestId", +// idNamespace: IdNamespace, +// parentClass: null, +// converters: StronglyTypedIdConverter.Default, +// backingType: StronglyTypedIdBackingType.Guid, +// implementations: StronglyTypedIdImplementations.None +// )); +// } +// +// [Fact] +// public void ThrowsWhenDefaultBackingTypeIsUsed() +// { +// Assert.Throws(() => SourceGenerationHelper.CreateId( +// idName: "MyTestId", +// idNamespace: IdNamespace, +// parentClass: null, +// converters: StronglyTypedIdConverter.None, +// backingType: StronglyTypedIdBackingType.Default, +// implementations: StronglyTypedIdImplementations.None +// )); +// } +// +// [Fact] +// public void ThrowsWhenDefaultImplementationsIsUsed() +// { +// Assert.Throws(() => SourceGenerationHelper.CreateId( +// idName: "MyTestId", +// idNamespace: IdNamespace, +// parentClass: null, +// converters: StronglyTypedIdConverter.None, +// backingType: StronglyTypedIdBackingType.Guid, +// implementations: StronglyTypedIdImplementations.Default +// )); +// } +// +// [Theory] +// [MemberData(nameof(Parameters))] +// public Task GeneratesIdCorrectly( +// StronglyTypedIdBackingType type, +// StronglyTypedIdConverter c, +// StronglyTypedIdImplementations i) +// { +// const string idName = "MyTestId"; +// var result = SourceGenerationHelper.CreateId( +// idName: idName, +// idNamespace: "", +// parentClass: null, +// converters: c, +// backingType: type, +// implementations: i +// ); +// +// return Verifier.Verify(result) +// .UseDirectory("Snapshots") +// .UseParameters(type, c, i); +// } +// +// [Theory] +// [MemberData(nameof(BackingTypes))] +// public Task GeneratesFullIdCorrectly(StronglyTypedIdBackingType type) +// { +// // combine them all +// var combinedConverter = EnumHelper.AllConverters(includeDefault: false) +// .Aggregate(StronglyTypedIdConverter.None, (prev, current) => prev | current); +// +// // combine them all +// var combinedImplementation = EnumHelper.AllImplementations(includeDefault: false) +// .Aggregate(StronglyTypedIdImplementations.None, (prev, current) => prev | current); +// +// const string idName = "MyTestId"; +// +// var result = SourceGenerationHelper.CreateId( +// idName: idName, +// idNamespace: "", +// parentClass: null, +// converters: combinedConverter, +// backingType: type, +// implementations: combinedImplementation +// ); +// +// return Verifier.Verify(result) +// .UseDirectory("Snapshots") +// .UseParameters(type); +// } +// +// [Theory] +// [InlineData(0)] +// [InlineData(1)] +// [InlineData(2)] +// public Task GeneratesIdWithNestedClassCorrectly(int nestedClassCount) +// { +// var parent = new ParentClass("record", "InnerMost", string.Empty, child: null); +// for (int i = 0; i < nestedClassCount; i++) +// { +// parent = new ParentClass("class", "OuterLayer" + i, string.Empty, parent); +// } +// +// var result = SourceGenerationHelper.CreateId( +// idName: "MyTestId", +// idNamespace: "MyTestNamespace", +// parentClass: parent, +// converters: StronglyTypedIdConverter.SystemTextJson, +// backingType: StronglyTypedIdBackingType.Guid, +// implementations: StronglyTypedIdImplementations.None +// ); +// +// return Verifier.Verify(result) +// .UseDirectory("Snapshots") +// .UseParameters(nestedClassCount); +// } +// +// public static IEnumerable BackingTypes() +// => EnumHelper.AllBackingTypes(includeDefault: false) +// .Select(x => new object[] { x }); +// +// public static IEnumerable Parameters() +// { +// foreach (var backingType in EnumHelper.AllBackingTypes(includeDefault: false)) +// { +// // All individual convert types +// foreach (var converter in EnumHelper.AllConverters(includeDefault: false)) +// { +// yield return new object[] { backingType, converter, StronglyTypedIdImplementations.None }; +// } +// +// // All individual implementations +// foreach (var implementation in EnumHelper.AllImplementations(includeDefault: false)) +// { +// if (implementation is StronglyTypedIdImplementations.None) +// { +// // We've already covered this one in the previous loop +// continue; +// } +// yield return new object[] { backingType, StronglyTypedIdConverter.None, implementation }; +// } +// } +// } +// } +// } \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIdConfiguration.cs b/test/StronglyTypedIds.Tests/StronglyTypedIdConfiguration.cs deleted file mode 100644 index a667c3caa..000000000 --- a/test/StronglyTypedIds.Tests/StronglyTypedIdConfiguration.cs +++ /dev/null @@ -1,211 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Xunit; - -namespace StronglyTypedIds.Tests -{ - public class StronglyTypedIdConfigurationTests - { - [Theory] - [MemberData(nameof(ExpectedBackingTypes))] - public void ReturnsCorrectBackingType_WhenNoDefaultAttribute(StronglyTypedIdBackingType attributeValue, StronglyTypedIdBackingType expected) - { - var attributeValues = new StronglyTypedIdConfiguration(attributeValue, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default); - - var result = StronglyTypedIdConfiguration.Combine(attributeValues, null); - - Assert.Equal(expected, result.BackingType); - } - - [Theory] - [MemberData(nameof(ExpectedBackingTypes))] - public void ReturnsCorrectBackingType_WhenHaveDefaultAttributeThatUsesDefault(StronglyTypedIdBackingType attributeValue, StronglyTypedIdBackingType expected) - { - var defaultAttribute = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default); - var attributeValues = new StronglyTypedIdConfiguration(attributeValue, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default); - - var result = StronglyTypedIdConfiguration.Combine(attributeValues, defaultAttribute); - - Assert.Equal(expected, result.BackingType); - } - - [Theory] - [MemberData(nameof(ExpectedBackingTypesWithDefault))] - public void ReturnsCorrectBackingType_WhenHaveDefaultAttribute(StronglyTypedIdBackingType attributeValue, StronglyTypedIdBackingType defaultValue, StronglyTypedIdBackingType expected) - { - var defaultAttribute = new StronglyTypedIdConfiguration(defaultValue, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default); - var attributeValues = new StronglyTypedIdConfiguration(attributeValue, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default); - - var result = StronglyTypedIdConfiguration.Combine(attributeValues, defaultAttribute); - - Assert.Equal(expected, result.BackingType); - } - - [Theory] - [MemberData(nameof(ExpectedConverters))] - public void ReturnsCorrectConverters_WhenNoDefaultAttribute(StronglyTypedIdConverter attributeValue, StronglyTypedIdConverter expected) - { - var attributeValues = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, attributeValue, StronglyTypedIdImplementations.Default); - - var result = StronglyTypedIdConfiguration.Combine(attributeValues, null); - - Assert.Equal(expected, result.Converters); - } - - [Theory] - [MemberData(nameof(ExpectedConverters))] - public void ReturnsCorrectConverters_WhenHaveDefaultAttributeThatUsesDefault(StronglyTypedIdConverter attributeValue, StronglyTypedIdConverter expected) - { - var defaultAttribute = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default); - var attributeValues = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, attributeValue, StronglyTypedIdImplementations.Default); - - var result = StronglyTypedIdConfiguration.Combine(attributeValues, defaultAttribute); - - Assert.Equal(expected, result.Converters); - } - - [Theory] - [MemberData(nameof(ExpectedConvertersWithDefault))] - public void ReturnsCorrectConverters_WhenHaveDefaultAttribute(StronglyTypedIdConverter attributeValue, StronglyTypedIdConverter defaultValue, StronglyTypedIdConverter expected) - { - var defaultAttribute = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, defaultValue, StronglyTypedIdImplementations.Default); - var attributeValues = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, attributeValue, StronglyTypedIdImplementations.Default); - - var result = StronglyTypedIdConfiguration.Combine(attributeValues, defaultAttribute); - - Assert.Equal(expected, result.Converters); - } - - [Theory] - [MemberData(nameof(ExpectedImplementations))] - public void ReturnsCorrectImplementations_WhenNoDefaultAttribute(StronglyTypedIdImplementations attributeValue, StronglyTypedIdImplementations expected) - { - var attributeValues = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, StronglyTypedIdConverter.Default, attributeValue); - - var result = StronglyTypedIdConfiguration.Combine(attributeValues, null); - - Assert.Equal(expected, result.Implementations); - } - - [Theory] - [MemberData(nameof(ExpectedImplementations))] - public void ReturnsCorrectImplementations_WhenHaveDefaultAttributeThatUsesDefault(StronglyTypedIdImplementations attributeValue, StronglyTypedIdImplementations expected) - { - var defaultAttribute = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, StronglyTypedIdConverter.Default, StronglyTypedIdImplementations.Default); - var attributeValues = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, StronglyTypedIdConverter.Default, attributeValue); - - var result = StronglyTypedIdConfiguration.Combine(attributeValues, defaultAttribute); - - Assert.Equal(expected, result.Implementations); - } - - [Theory] - [MemberData(nameof(ExpectedImplementationsWithDefault))] - public void ReturnsCorrectImplementations_WhenHaveDefaultAttribute(StronglyTypedIdImplementations attributeValue, StronglyTypedIdImplementations defaultValue, StronglyTypedIdImplementations expected) - { - var defaultAttribute = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, StronglyTypedIdConverter.Default, defaultValue); - var attributeValues = new StronglyTypedIdConfiguration(StronglyTypedIdBackingType.Default, StronglyTypedIdConverter.Default, attributeValue); - - var result = StronglyTypedIdConfiguration.Combine(attributeValues, defaultAttribute); - - Assert.Equal(expected, result.Implementations); - } - - public static IEnumerable ExpectedBackingTypes() - { - foreach (var backingType in EnumHelper.AllBackingTypes(includeDefault: false)) - { - // attribute, expected - yield return new object[] { backingType, backingType }; - } - - yield return new object[] { StronglyTypedIdBackingType.Default, StronglyTypedIdConfiguration.Defaults.BackingType }; - } - - public static IEnumerable ExpectedBackingTypesWithDefault() - { - foreach (var attributeType in EnumHelper.AllBackingTypes(includeDefault: false)) - { - foreach (var defaultType in EnumHelper.AllBackingTypes(includeDefault: true)) - { - // attribute, default, expected - yield return new object[] { attributeType, defaultType, attributeType }; - } - } - - foreach (var defaultType in EnumHelper.AllBackingTypes(includeDefault: false)) - { - // attribute, default, expected - yield return new object[] { StronglyTypedIdBackingType.Default, defaultType, defaultType }; - } - - yield return new object[] { StronglyTypedIdBackingType.Default, StronglyTypedIdBackingType.Default, StronglyTypedIdConfiguration.Defaults.BackingType }; - } - - - public static IEnumerable ExpectedConverters() - { - foreach (var backingType in EnumHelper.AllConverterCombinations(includeDefault: false, includeNone: false)) - { - // attribute, expected - yield return new object[] { backingType, backingType }; - } - - yield return new object[] { StronglyTypedIdConverter.None, StronglyTypedIdConverter.None }; - yield return new object[] { StronglyTypedIdConverter.Default, StronglyTypedIdConfiguration.Defaults.Converters }; - } - - public static IEnumerable ExpectedConvertersWithDefault() - { - foreach (var attributeType in EnumHelper.AllConverterCombinations(includeDefault: false)) - { - foreach (var defaultType in EnumHelper.AllConverterCombinations(includeDefault: true)) - { - // attribute, default, expected - yield return new object[] { attributeType, defaultType, attributeType }; - } - } - - foreach (var defaultType in EnumHelper.AllConverterCombinations(includeDefault: false)) - { - // attribute, default, expected - yield return new object[] { StronglyTypedIdConverter.Default, defaultType, defaultType }; - } - - yield return new object[] { StronglyTypedIdConverter.Default, StronglyTypedIdConverter.Default, StronglyTypedIdConfiguration.Defaults.Converters }; - } - - public static IEnumerable ExpectedImplementations() - { - foreach (var backingType in EnumHelper.AllImplementationCombinations(includeDefault: false, includeNone: false)) - { - // attribute, expected - yield return new object[] { backingType, backingType }; - } - - yield return new object[] { StronglyTypedIdImplementations.None, StronglyTypedIdImplementations.None }; - yield return new object[] { StronglyTypedIdImplementations.Default, StronglyTypedIdConfiguration.Defaults.Implementations }; - } - - public static IEnumerable ExpectedImplementationsWithDefault() - { - foreach (var attributeType in EnumHelper.AllImplementations(includeDefault: false)) - { - foreach (var defaultType in EnumHelper.AllImplementations(includeDefault: true)) - { - // attribute, default, expected - yield return new object[] { attributeType, defaultType, attributeType }; - } - } - - foreach (var defaultType in EnumHelper.AllImplementations(includeDefault: false)) - { - // attribute, default, expected - yield return new object[] { StronglyTypedIdImplementations.Default, defaultType, defaultType }; - } - - yield return new object[] { StronglyTypedIdImplementations.Default, StronglyTypedIdImplementations.Default, StronglyTypedIdConfiguration.Defaults.Implementations }; - } - } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs index bf9a4912a..597716f00 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs +++ b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs @@ -39,7 +39,7 @@ public Task CanGenerateIdInNamespace() namespace SomeNamespace { - [StronglyTypedId] + [StronglyTypedId()] public partial struct MyId {} }"; var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); @@ -116,11 +116,14 @@ public partial struct MyId {} [Fact] public Task CanOverrideDefaultsUsingGlobalAttribute() { - const string input = @"using StronglyTypedIds; -[assembly:StronglyTypedIdDefaults(backingType: StronglyTypedIdBackingType.Int, converters: StronglyTypedIdConverter.None)] + const string input = """ + using StronglyTypedIds; + [assembly:StronglyTypedIdDefaults("int")] + + [StronglyTypedId] + public partial struct MyId {} + """; -[StronglyTypedId] -public partial struct MyId {}"; var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); Assert.Empty(diagnostics); @@ -132,12 +135,14 @@ public partial struct MyId {}"; [Fact] public Task MultipleAssemblyAttributesGeneratesWithDefault() { - const string input = @"using StronglyTypedIds; -[assembly:StronglyTypedIdDefaults(backingType: StronglyTypedIdBackingType.Int, converters: StronglyTypedIdConverter.None)] -[assembly:StronglyTypedIdDefaults(backingType: StronglyTypedIdBackingType.Long, converters: StronglyTypedIdConverter.None)] - -[StronglyTypedId] -public partial struct MyId {}"; + const string input = """ + using StronglyTypedIds; + [assembly:StronglyTypedIdDefaults("int")] + [assembly:StronglyTypedIdDefaults("long")] + + [StronglyTypedId] + public partial struct MyId {} + """; var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); Assert.Contains(diagnostics, diagnostic => diagnostic.Id == MultipleAssemblyAttributeDiagnostic.Id); @@ -146,60 +151,6 @@ public partial struct MyId {}"; .UseDirectory("Snapshots"); } - [Theory] - [MemberData(nameof(GetData))] - public Task CanGenerateIdWithNamedParameters(StronglyTypedIdBackingType backingType, StronglyTypedIdConverter? converter) - { - var type = $"backingType: {nameof(StronglyTypedIdBackingType)}.{backingType.ToString()}"; - var converters = converter.HasValue - ? $", converters: {ToArgument(converter.Value)}" - : string.Empty; - var attribute = $"[StronglyTypedId({type}{converters})]"; - - _output.WriteLine(attribute); - - var input = @"using StronglyTypedIds; - -namespace MyTests.TestNameSpace -{ - " + attribute + @" - public partial struct MyId {} -}"; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); - - Assert.Empty(diagnostics); - - return Verifier.Verify(output) - .UseParameters(backingType, converter) - .UseDirectory("Snapshots"); - } - - [Theory] - [MemberData(nameof(GetData))] - public Task CanGenerateIdWithPositionalParameters(StronglyTypedIdBackingType backingType, StronglyTypedIdConverter? converter) - { - var type = $"{nameof(StronglyTypedIdBackingType)}.{backingType.ToString()}"; - var args = converter.HasValue ? $"{type}, {ToArgument(converter.Value)}" : $"{type}"; - var attribute = $"[StronglyTypedId({args})]"; - - _output.WriteLine(attribute); - - var input = @"using StronglyTypedIds; - -namespace MyTests.TestNameSpace -{ - " + attribute + @" - public partial struct MyId {} -}"; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); - - Assert.Empty(diagnostics); - - return Verifier.Verify(output) - .UseParameters(backingType, converter) - .UseDirectory("Snapshots"); - } - [Fact] public Task CanGenerateMultipleIdsWithSameName() { @@ -226,26 +177,5 @@ public partial struct MyId {} return Verifier.Verify(output) .UseDirectory("Snapshots"); } - - public static TheoryData GetData => new() - { - {StronglyTypedIdBackingType.Guid, null}, - {StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.NewtonsoftJson}, - {StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.SystemTextJson}, - {StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.TypeConverter}, - {StronglyTypedIdBackingType.Guid, StronglyTypedIdConverter.SystemTextJson | StronglyTypedIdConverter.NewtonsoftJson}, - }; - - public static string ToArgument(StronglyTypedIdConverter converter) => - converter switch - { - StronglyTypedIdConverter.NewtonsoftJson => "StronglyTypedIdConverter.NewtonsoftJson", - StronglyTypedIdConverter.SystemTextJson => "StronglyTypedIdConverter.SystemTextJson", - StronglyTypedIdConverter.TypeConverter => "StronglyTypedIdConverter.TypeConverter", - _ when converter.HasFlag(StronglyTypedIdConverter.NewtonsoftJson) && - converter.HasFlag(StronglyTypedIdConverter.SystemTextJson) => - "StronglyTypedIdConverter.NewtonsoftJson | StronglyTypedIdConverter.SystemTextJson", - _ => throw new InvalidOperationException("Unknown converter " + converter), - }; } } \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj index 4fc7f0fb2..5eb727e13 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj +++ b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj @@ -18,9 +18,28 @@ + + + + Templates\guid.typedid + + + Templates\int.typedid + + + Templates\long.typedid + + + + + + + + + diff --git a/test/StronglyTypedIds.Tests/TestHelpers.cs b/test/StronglyTypedIds.Tests/TestHelpers.cs index 7b99488a6..4be1e841a 100644 --- a/test/StronglyTypedIds.Tests/TestHelpers.cs +++ b/test/StronglyTypedIds.Tests/TestHelpers.cs @@ -1,10 +1,14 @@ using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.IO; using System.Linq; +using System.Reflection; using System.Text; +using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Text; namespace StronglyTypedIds.Tests { @@ -13,6 +17,7 @@ internal static class TestHelpers public static (ImmutableArray Diagnostics, string Output) GetGeneratedOutput(string source) where T : IIncrementalGenerator, new() { + var attr = new StronglyTypedIdAttribute(); var syntaxTree = CSharpSyntaxTree.ParseText(source); var references = AppDomain.CurrentDomain.GetAssemblies() .Where(_ => !_.IsDynamic && !string.IsNullOrWhiteSpace(_.Location)) @@ -28,15 +33,27 @@ public static (ImmutableArray Diagnostics, string Output) GetGenerat CSharpGeneratorDriver .Create(new T()) + .AddAdditionalTexts(LoadEmbeddedResourcesAsAdditionalText()) .RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var diagnostics); var output = string.Join("\n", outputCompilation.SyntaxTrees.Skip(originalTreeCount).Select(t => t.ToString())); return (diagnostics, output); } - internal static string LoadEmbeddedResource(string resourceName) + private static ImmutableArray LoadEmbeddedResourcesAsAdditionalText() { + var texts = ImmutableArray.CreateBuilder(); var assembly = typeof(TestHelpers).Assembly; + + texts.AddRange(assembly.GetManifestResourceNames() + .Select(name => new TestAdditionalText( + text: LoadEmbeddedResource(assembly, name), + path: $"C:\\test\\Templates\\{Path.GetExtension(Path.GetFileNameWithoutExtension(name)).Substring(1)}.txt"))); + + return texts.ToImmutable(); + } + private static string LoadEmbeddedResource(Assembly assembly, string resourceName) + { var resourceStream = assembly.GetManifestResourceStream(resourceName); if (resourceStream is null) { @@ -48,5 +65,111 @@ internal static string LoadEmbeddedResource(string resourceName) return reader.ReadToEnd(); } + + private sealed class TestAdditionalText : AdditionalText + { + private readonly SourceText _text; + + public TestAdditionalText(string path, SourceText text) + { + Path = path; + _text = text; + } + + public TestAdditionalText(string text = "", Encoding encoding = null, string path = "dummy", SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1) + : this(path, new StringText(text, encoding, checksumAlgorithm: checksumAlgorithm)) + { + } + + public override string Path { get; } + + public override SourceText GetText(CancellationToken cancellationToken = default) => _text; + } + + /// + /// Implementation of SourceText based on a input + /// + internal sealed class StringText : SourceText + { + private readonly string _source; + private readonly Encoding _encodingOpt; + + internal StringText( + string source, + Encoding encodingOpt, + ImmutableArray checksum = default(ImmutableArray), + SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1) + : base(checksum, checksumAlgorithm) + { + _source = source; + _encodingOpt = encodingOpt; + } + + public override Encoding Encoding => _encodingOpt; + + /// + /// Underlying string which is the source of this instance + /// + public string Source => _source; + + /// + /// The length of the text represented by . + /// + public override int Length => _source.Length; + + /// + /// Returns a character at given position. + /// + /// The position to get the character from. + /// The character. + /// When position is negative or + /// greater than . + public override char this[int position] + { + get + { + // NOTE: we are not validating position here as that would not + // add any value to the range check that string accessor performs anyways. + + return _source[position]; + } + } + + /// + /// Provides a string representation of the StringText located within given span. + /// + /// When given span is outside of the text range. + public override string ToString(TextSpan span) + { + if (span.End > this.Source.Length) + { + throw new ArgumentOutOfRangeException(nameof(span)); + } + + if (span.Start == 0 && span.Length == this.Length) + { + return this.Source; + } + + return this.Source.Substring(span.Start, span.Length); + } + + public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) + { + this.Source.CopyTo(sourceIndex, destination, destinationIndex, count); + } + + public override void Write(TextWriter textWriter, TextSpan span, CancellationToken cancellationToken = default(CancellationToken)) + { + if (span.Start == 0 && span.End == this.Length) + { + textWriter.Write(this.Source); + } + else + { + base.Write(textWriter, span, cancellationToken); + } + } + } } } \ No newline at end of file From bd7b5af48a73212b08a8c5bbcada64dd7ec9a370 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Wed, 1 Nov 2023 18:18:30 +0000 Subject: [PATCH 03/47] wip --- StronglyTypedId.sln | 15 + .../StronglyTypedIds.Templates.csproj | 11 + .../StronglyTypedIds.Templates.targets | 8 + .../StronglyTypedIds.Templates/newid.typedid | 55 +- src/StronglyTypedIds/EmbeddedSources.Guid.cs | 12 +- src/StronglyTypedIds/EmbeddedSources.Int.cs | 201 +++++ src/StronglyTypedIds/EmbeddedSources.cs | 1 + src/StronglyTypedIds/ParentClass.cs | 17 - src/StronglyTypedIds/Parser.cs | 17 +- .../SourceGenerationHelper.cs | 22 +- src/StronglyTypedIds/StronglyTypedIds.csproj | 6 +- src/StronglyTypedIds/StructToGenerate.cs | 15 +- .../Templates/Guid/Guid_DapperTypeHandler.cs | 12 +- .../Guid/Guid_EfCoreValueConverter.cs | 4 +- .../Guid/Guid_NewtonsoftJsonConverter.cs | 8 +- .../Templates/Int/Int_DapperTypeHandler.cs | 14 +- .../Templates/Int/Int_EfCoreValueConverter.cs | 4 +- .../Int/Int_NewtonsoftJsonConverter.cs | 8 +- .../Templates/guid-full.typedid | 248 ++++++ src/StronglyTypedIds/Templates/guid.typedid | 69 -- .../Templates/int-full.typedid | 244 ++++++ src/StronglyTypedIds/Templates/int.typedid | 68 -- test/IntegrationLibraries.props | 6 + .../DapperTypeHandlers.cs | 12 +- .../DefaultIdTests.cs | 14 - .../Enums.cs | 99 +-- .../GuidIdTests.cs | 309 ++++---- .../IntIdTests.cs | 682 ++++++++-------- .../StronglyTypedIds.IntegrationTests.csproj | 1 + .../EmbeddedResourceTests.cs | 1 + test/StronglyTypedIds.Tests/EqualityTests.cs | 10 +- ...ledResource_resource=Template.verified.txt | 31 + ...atesFullIdCorrectly_type=Guid.verified.txt | 143 ---- ...ratesFullIdCorrectly_type=Int.verified.txt | 143 ---- ...atesFullIdCorrectly_type=Long.verified.txt | 146 ---- ...rrectly_type=MassTransitNewId.verified.txt | 151 ---- ...Correctly_type=NullableString.verified.txt | 175 ----- ...esFullIdCorrectly_type=String.verified.txt | 161 ---- ...id_c=DapperTypeHandler_i=None.verified.txt | 54 -- ...c=EfCoreValueConverter_i=None.verified.txt | 47 -- ...=Guid_c=NewtonsoftJson_i=None.verified.txt | 57 -- ...ype=Guid_c=None_i=IComparable.verified.txt | 37 - ...type=Guid_c=None_i=IEquatable.verified.txt | 36 - ...ectly_type=Guid_c=None_i=None.verified.txt | 36 - ...=Guid_c=SystemTextJson_i=None.verified.txt | 50 -- ...e=Guid_c=TypeConverter_i=None.verified.txt | 78 -- ...nt_c=DapperTypeHandler_i=None.verified.txt | 54 -- ...c=EfCoreValueConverter_i=None.verified.txt | 46 -- ...e=Int_c=NewtonsoftJson_i=None.verified.txt | 56 -- ...type=Int_c=None_i=IComparable.verified.txt | 36 - ..._type=Int_c=None_i=IEquatable.verified.txt | 35 - ...rectly_type=Int_c=None_i=None.verified.txt | 35 - ...e=Int_c=SystemTextJson_i=None.verified.txt | 49 -- ...pe=Int_c=TypeConverter_i=None.verified.txt | 77 -- ...ng_c=DapperTypeHandler_i=None.verified.txt | 55 -- ...c=EfCoreValueConverter_i=None.verified.txt | 46 -- ...=Long_c=NewtonsoftJson_i=None.verified.txt | 56 -- ...ype=Long_c=None_i=IComparable.verified.txt | 36 - ...type=Long_c=None_i=IEquatable.verified.txt | 35 - ...ectly_type=Long_c=None_i=None.verified.txt | 35 - ...=Long_c=SystemTextJson_i=None.verified.txt | 49 -- ...e=Long_c=TypeConverter_i=None.verified.txt | 79 -- ...Id_c=DapperTypeHandler_i=None.verified.txt | 54 -- ...c=EfCoreValueConverter_i=None.verified.txt | 47 -- ...NewId_c=NewtonsoftJson_i=None.verified.txt | 57 -- ...sitNewId_c=None_i=IComparable.verified.txt | 37 - ...nsitNewId_c=None_i=IEquatable.verified.txt | 36 - ...assTransitNewId_c=None_i=None.verified.txt | 36 - ...NewId_c=SystemTextJson_i=None.verified.txt | 50 -- ...ng_c=DapperTypeHandler_i=None.verified.txt | 63 -- ...c=EfCoreValueConverter_i=None.verified.txt | 55 -- ...tring_c=NewtonsoftJson_i=None.verified.txt | 71 -- ...leString_c=None_i=IComparable.verified.txt | 54 -- ...bleString_c=None_i=IEquatable.verified.txt | 44 -- ...=NullableString_c=None_i=None.verified.txt | 44 -- ...tring_c=SystemTextJson_i=None.verified.txt | 65 -- ...String_c=TypeConverter_i=None.verified.txt | 87 -- ...ng_c=DapperTypeHandler_i=None.verified.txt | 61 -- ...c=EfCoreValueConverter_i=None.verified.txt | 55 -- ...tring_c=NewtonsoftJson_i=None.verified.txt | 71 -- ...e=String_c=None_i=IComparable.verified.txt | 54 -- ...pe=String_c=None_i=IEquatable.verified.txt | 44 -- ...tly_type=String_c=None_i=None.verified.txt | 44 -- ...tring_c=SystemTextJson_i=None.verified.txt | 58 -- ...String_c=TypeConverter_i=None.verified.txt | 82 -- ...sCorrectly_nestedClassCount=0.verified.txt | 56 -- ...sCorrectly_nestedClassCount=1.verified.txt | 59 -- ...sCorrectly_nestedClassCount=2.verified.txt | 62 -- ...ltIdInGlobalNamespace.Core3_1.received.txt | 522 ++++++++++++ ...IdInGlobalNamespace.DotNet6_0.received.txt | 522 ++++++++++++ ...IdInGlobalNamespace.DotNet7_0.received.txt | 522 ++++++++++++ ...ultIdInGlobalNamespace.Net4_8.received.txt | 522 ++++++++++++ ...ateDefaultIdInGlobalNamespace.verified.txt | 284 ++++++- ...CanGenerateForCustomTemplate.verified.txt} | 150 +++- ...dInFileScopeNamespace.Core3_1.received.txt | 532 +++++++++++++ ...nFileScopeNamespace.DotNet6_0.received.txt | 532 +++++++++++++ ...nFileScopeNamespace.DotNet7_0.received.txt | 532 +++++++++++++ ...IdInFileScopeNamespace.Net4_8.received.txt | 532 +++++++++++++ ...yNestedIdInFileScopeNamespace.verified.txt | 531 +++++++++++++ ...InFileScopedNamespace.Core3_1.received.txt | 525 +++++++++++++ ...FileScopedNamespace.DotNet6_0.received.txt | 525 +++++++++++++ ...FileScopedNamespace.DotNet7_0.received.txt | 525 +++++++++++++ ...dInFileScopedNamespace.Net4_8.received.txt | 525 +++++++++++++ ...nerateIdInFileScopedNamespace.verified.txt | 284 ++++++- ...GenerateIdInNamespace.Core3_1.received.txt | 525 +++++++++++++ ...nerateIdInNamespace.DotNet6_0.received.txt | 525 +++++++++++++ ...nerateIdInNamespace.DotNet7_0.received.txt | 13 +- ...nGenerateIdInNamespace.Net4_8.received.txt | 525 +++++++++++++ ...ests.CanGenerateIdInNamespace.verified.txt | 284 ++++++- ...ewtonsoftJson, SystemTextJson.verified.txt | 293 ------- ...Guid_converter=NewtonsoftJson.verified.txt | 279 ------- ...Guid_converter=SystemTextJson.verified.txt | 272 ------- ...=Guid_converter=TypeConverter.verified.txt | 300 ------- ...ewtonsoftJson, SystemTextJson.verified.txt | 293 ------- ...Guid_converter=NewtonsoftJson.verified.txt | 279 ------- ...Guid_converter=SystemTextJson.verified.txt | 272 ------- ...=Guid_converter=TypeConverter.verified.txt | 300 ------- ...ltipleIdsWithSameName.Core3_1.received.txt | 742 ++++++++++++++++++ ...ipleIdsWithSameName.DotNet6_0.received.txt | 742 ++++++++++++++++++ ...ipleIdsWithSameName.DotNet7_0.received.txt | 742 ++++++++++++++++++ ...ultipleIdsWithSameName.Net4_8.received.txt | 742 ++++++++++++++++++ ...nerateMultipleIdsWithSameName.verified.txt | 594 ++++++++++++-- ...dInFileScopeNamespace.Core3_1.received.txt | 528 +++++++++++++ ...nFileScopeNamespace.DotNet6_0.received.txt | 528 +++++++++++++ ...nFileScopeNamespace.DotNet7_0.received.txt | 528 +++++++++++++ ...IdInFileScopeNamespace.Net4_8.received.txt | 528 +++++++++++++ ...eNestedIdInFileScopeNamespace.verified.txt | 426 +++++++++- ...nerateNonDefaultIdInNamespace.verified.txt | 520 ++++++++++++ ...dInFileScopeNamespace.Core3_1.received.txt | 534 +++++++++++++ ...nFileScopeNamespace.DotNet6_0.received.txt | 534 +++++++++++++ ...nFileScopeNamespace.DotNet7_0.received.txt | 534 +++++++++++++ ...IdInFileScopeNamespace.Net4_8.received.txt | 534 +++++++++++++ ...yNestedIdInFileScopeNamespace.verified.txt | 430 +++++++++- ...singGlobalAttribute.DotNet7_0.received.txt | 521 ++++++++++++ ...eDefaultsUsingGlobalAttribute.verified.txt | 155 +--- ...TemplateUsingGlobalAttribute.verified.txt} | 151 +++- ...eUsingGlobalAttribute.Core3_1.received.txt | 517 ++++++++++++ ...singGlobalAttribute.DotNet6_0.received.txt | 517 ++++++++++++ ...singGlobalAttribute.DotNet7_0.received.txt | 517 ++++++++++++ ...teUsingGlobalAttribute.Net4_8.received.txt | 517 ++++++++++++ ...hTemplateUsingGlobalAttribute.verified.txt | 516 ++++++++++++ ...sGeneratesWithDefault.Core3_1.received.txt | 522 ++++++++++++ ...eneratesWithDefault.DotNet6_0.received.txt | 522 ++++++++++++ ...eneratesWithDefault.DotNet7_0.received.txt | 522 ++++++++++++ ...esGeneratesWithDefault.Net4_8.received.txt | 522 ++++++++++++ ...ttributesGeneratesWithDefault.verified.txt | 423 +++++++++- .../SourceGenerationHelperSnapshotTests.cs | 43 +- .../StronglyTypedIdGeneratorTests.cs | 107 ++- .../StronglyTypedIds.Tests.csproj | 15 +- test/StronglyTypedIds.Tests/TestHelpers.cs | 2 +- 150 files changed, 25682 insertions(+), 7081 deletions(-) create mode 100644 src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj create mode 100644 src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.targets rename test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=TypeConverter_i=None.verified.txt => src/StronglyTypedIds.Templates/newid.typedid (56%) create mode 100644 src/StronglyTypedIds/EmbeddedSources.Int.cs delete mode 100644 src/StronglyTypedIds/ParentClass.cs create mode 100644 src/StronglyTypedIds/Templates/guid-full.typedid delete mode 100644 src/StronglyTypedIds/Templates/guid.typedid create mode 100644 src/StronglyTypedIds/Templates/int-full.typedid delete mode 100644 src/StronglyTypedIds/Templates/int.typedid create mode 100644 test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Guid.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Int.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Long.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=MassTransitNewId.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=NullableString.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=String.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=DapperTypeHandler_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=EfCoreValueConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=NewtonsoftJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=IComparable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=IEquatable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=SystemTextJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=TypeConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=DapperTypeHandler_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=EfCoreValueConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=NewtonsoftJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=IComparable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=IEquatable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=SystemTextJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=TypeConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=DapperTypeHandler_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=EfCoreValueConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=NewtonsoftJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=IComparable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=IEquatable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=SystemTextJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=TypeConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=DapperTypeHandler_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=EfCoreValueConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=NewtonsoftJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=IComparable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=IEquatable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=SystemTextJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=DapperTypeHandler_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=EfCoreValueConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=NewtonsoftJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=IComparable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=IEquatable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=SystemTextJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=TypeConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=DapperTypeHandler_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=EfCoreValueConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=NewtonsoftJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=IComparable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=IEquatable.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=SystemTextJson_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=TypeConverter_i=None.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=0.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=1.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=2.verified.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Core3_1.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet6_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet7_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Net4_8.received.txt rename test/StronglyTypedIds.Tests/Snapshots/{StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=null.verified.txt => StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt} (68%) create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Core3_1.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Net4_8.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Core3_1.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet6_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet7_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Net4_8.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Core3_1.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet6_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Net4_8.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=NewtonsoftJson, SystemTextJson.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=NewtonsoftJson.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=SystemTextJson.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=TypeConverter.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=NewtonsoftJson, SystemTextJson.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=NewtonsoftJson.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=SystemTextJson.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=TypeConverter.verified.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Core3_1.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet6_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet7_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Net4_8.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Core3_1.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet6_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet7_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Net4_8.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Core3_1.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Net4_8.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.DotNet7_0.received.txt rename test/StronglyTypedIds.Tests/Snapshots/{StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=null.verified.txt => StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt} (68%) create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Core3_1.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet6_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet7_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Net4_8.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Core3_1.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet6_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet7_0.received.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Net4_8.received.txt diff --git a/StronglyTypedId.sln b/StronglyTypedId.sln index cd44309c6..84545c38b 100644 --- a/StronglyTypedId.sln +++ b/StronglyTypedId.sln @@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Nuget.Inte EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Nuget.Attributes.IntegrationTests", "test\StronglyTypedIds.Nuget.Attributes.IntegrationTests\StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj", "{19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Templates", "src\StronglyTypedIds.Templates\StronglyTypedIds.Templates.csproj", "{E0561C0B-A51D-4399-94A3-F44BA375AF4D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -104,6 +106,18 @@ Global {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}.Release|Any CPU.ActiveCfg = Release|Any CPU {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}.Release|x64.ActiveCfg = Release|Any CPU {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}.Release|x86.ActiveCfg = Release|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|x64.ActiveCfg = Debug|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|x64.Build.0 = Debug|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|x86.ActiveCfg = Debug|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|x86.Build.0 = Debug|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|Any CPU.Build.0 = Release|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|x64.ActiveCfg = Release|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|x64.Build.0 = Release|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|x86.ActiveCfg = Release|Any CPU + {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -115,6 +129,7 @@ Global {F25F6E67-E62A-4075-86CF-4C4EDD7E4883} = {EE1258BD-3422-4F55-B9CF-B4D6C95DAD68} {A7355210-7DDC-4968-84B7-79002113EA6E} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} + {E0561C0B-A51D-4399-94A3-F44BA375AF4D} = {EE1258BD-3422-4F55-B9CF-B4D6C95DAD68} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8D1F0534-B8AD-4CFA-9C14-CBC757BCB1E1} diff --git a/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj b/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj new file mode 100644 index 000000000..bc9b36ab9 --- /dev/null +++ b/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0;net461 + false + + + + + + diff --git a/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.targets b/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.targets new file mode 100644 index 000000000..9df47b89b --- /dev/null +++ b/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.targets @@ -0,0 +1,8 @@ + + + + + false + + + diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=TypeConverter_i=None.verified.txt b/src/StronglyTypedIds.Templates/newid.typedid similarity index 56% rename from test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=TypeConverter_i=None.verified.txt rename to src/StronglyTypedIds.Templates/newid.typedid index 757eb4ebb..e87f9f725 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=TypeConverter_i=None.verified.txt +++ b/src/StronglyTypedIds.Templates/newid.typedid @@ -1,41 +1,32 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId + [System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + readonly partial struct PLACEHOLDERID : INTERFACES { public MassTransit.NewId Value { get; } - public MyTestId(MassTransit.NewId value) + public PLACEHOLDERID(MassTransit.NewId value) { Value = value; } - public static MyTestId New() => new MyTestId(MassTransit.NewId.Next()); - public static readonly MyTestId Empty = new MyTestId(MassTransit.NewId.Empty); + public static PLACEHOLDERID New() => new PLACEHOLDERID(MassTransit.NewId.Next()); + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(MassTransit.NewId.Empty); - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); + return obj is PLACEHOLDERID other && Equals(other); } public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter + class PLACEHOLDERIDTypeConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) { @@ -48,9 +39,9 @@ { return value switch { - MassTransit.NewId newIdValue => new MyTestId(newIdValue), - System.Guid guidValue => new MyTestId(MassTransit.NewId.FromGuid(guidValue)), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyTestId(MassTransit.NewId.FromGuid(result)), + MassTransit.NewId newIdValue => new PLACEHOLDERID(newIdValue), + System.Guid guidValue => new PLACEHOLDERID(MassTransit.NewId.FromGuid(guidValue)), + string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(MassTransit.NewId.FromGuid(result)), _ => base.ConvertFrom(context, culture, value), }; } @@ -62,7 +53,7 @@ public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { - if (value is MyTestId idValue) + if (value is PLACEHOLDERID idValue) { if (destinationType == typeof(MassTransit.NewId)) { @@ -83,4 +74,16 @@ return base.ConvertTo(context, culture, value, destinationType); } } - } + + class PLACEHOLDERIDSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter + { + public override PLACEHOLDERID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) + { + return new PLACEHOLDERID(MassTransit.NewId.FromGuid(reader.GetGuid())); + } + + public override void Write(System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, System.Text.Json.JsonSerializerOptions options) + { + writer.WriteStringValue(value.Value.ToGuid()); + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.Guid.cs b/src/StronglyTypedIds/EmbeddedSources.Guid.cs index 6bd1c84e6..9bd791ead 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Guid.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Guid.cs @@ -3,13 +3,14 @@ namespace StronglyTypedIds; internal static partial class EmbeddedSources { private const string GuidTemplate = """ - partial struct PLACEHOLDERID: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + partial struct PLACEHOLDERID : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable - #if NET7_OR_GREATER - global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif + #if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public global::System.Guid Value { get; } @@ -21,7 +22,6 @@ public PLACEHOLDERID(global::System.Guid value) public static PLACEHOLDERID New() => new PLACEHOLDERID(global::System.Guid.NewGuid()); public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(global::System.Guid.Empty); - /// public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); public override bool Equals(object? obj) @@ -57,7 +57,7 @@ public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescripto }; } - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type? sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } diff --git a/src/StronglyTypedIds/EmbeddedSources.Int.cs b/src/StronglyTypedIds/EmbeddedSources.Int.cs new file mode 100644 index 000000000..6d44ba12c --- /dev/null +++ b/src/StronglyTypedIds/EmbeddedSources.Int.cs @@ -0,0 +1,201 @@ +namespace StronglyTypedIds; + +internal static partial class EmbeddedSources +{ + private const string IntTemplate = """ + partial struct PLACEHOLDERID : + #if NET6_0_OR_GREATER + global::System.ISpanFormattable, + #endif + #if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, + #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public int Value { get; } + + public PLACEHOLDERID(int value) + { + Value = value; + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(0); + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + int intValue => new PLACEHOLDERID(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + + #if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt32()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); + #endif + } + + public static PLACEHOLDERID Parse(string input) + => new(int.Parse(input)); + + #if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(int.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (int.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } + #endif + + /// + public string ToString( + #if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + #endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + + #if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(int.Parse(input)); + #endif + + #if NET6_0_OR_GREATER + #if NET7_0_OR_GREATER + /// + #endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) + #if NET7_0_OR_GREATER + => new(int.Parse(input, provider)); + #else + => new(int.Parse(input)); + #endif + + #if NET7_0_OR_GREATER + /// + #endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { + #if NET7_0_OR_GREATER + if (int.TryParse(input, provider, out var guid)) + #else + if (int.TryParse(input, out var guid)) + #endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + #if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + #endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + #if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + #endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); + #endif + } + """; +} \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.cs b/src/StronglyTypedIds/EmbeddedSources.cs index 8ffcf3200..a9f644863 100644 --- a/src/StronglyTypedIds/EmbeddedSources.cs +++ b/src/StronglyTypedIds/EmbeddedSources.cs @@ -21,6 +21,7 @@ internal static string GetTemplate(Template template) => template switch { Template.Guid => GuidTemplate, + Template.Int => IntTemplate, _ => string.Empty, }; diff --git a/src/StronglyTypedIds/ParentClass.cs b/src/StronglyTypedIds/ParentClass.cs deleted file mode 100644 index 01f6036ff..000000000 --- a/src/StronglyTypedIds/ParentClass.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace StronglyTypedIds; - -internal record ParentClass -{ - public ParentClass(string keyword, string name, string constraints, ParentClass? child) - { - Keyword = keyword; - Name = name; - Constraints = constraints; - Child = child; - } - - public ParentClass? Child { get; } - public string Keyword { get; } - public string Name { get; } - public string Constraints { get; } -} \ No newline at end of file diff --git a/src/StronglyTypedIds/Parser.cs b/src/StronglyTypedIds/Parser.cs index 6e280ab48..3855f539a 100644 --- a/src/StronglyTypedIds/Parser.cs +++ b/src/StronglyTypedIds/Parser.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -70,7 +71,10 @@ internal static class Parser ParentClass? parentClass = GetParentClasses(structSyntax); var name = structSymbol.Name; - var toGenerate = new StructToGenerate(name: name, nameSpace: nameSpace, templateName: templateName, parent: parentClass); + var toGenerate = template.HasValue + ? new StructToGenerate(name: name, nameSpace: nameSpace, template: template.Value, parent: parentClass) + : new StructToGenerate(name: name, nameSpace: nameSpace, templateName: templateName, parent: parentClass); + return new Result<(StructToGenerate, bool)>((toGenerate, true), errors); } @@ -240,10 +244,12 @@ potentialNamespaceParent is not NamespaceDeclarationSyntax while (parentIdClass != null && IsAllowedKind(parentIdClass.Kind())) { parentClass = new ParentClass( - keyword: parentIdClass.Keyword.ValueText, - name: parentIdClass.Identifier.ToString() + parentIdClass.TypeParameterList, - constraints: parentIdClass.ConstraintClauses.ToString(), - child: parentClass); + Modifiers: parentIdClass.Modifiers.ToString(), + Keyword: parentIdClass.Keyword.ValueText, + Name: parentIdClass.Identifier.ToString() + parentIdClass.TypeParameterList, + Constraints: parentIdClass.ConstraintClauses.ToString(), + Child: parentClass, + IsGeneric: parentIdClass.Arity > 0); parentIdClass = (parentIdClass.Parent as TypeDeclarationSyntax); } @@ -253,6 +259,7 @@ potentialNamespaceParent is not NamespaceDeclarationSyntax static bool IsAllowedKind(SyntaxKind kind) => kind == SyntaxKind.ClassDeclaration || kind == SyntaxKind.StructDeclaration || + kind == SyntaxKind.RecordStructDeclaration || kind == SyntaxKind.RecordDeclaration; } } \ No newline at end of file diff --git a/src/StronglyTypedIds/SourceGenerationHelper.cs b/src/StronglyTypedIds/SourceGenerationHelper.cs index 264fdb0e6..d113056d0 100644 --- a/src/StronglyTypedIds/SourceGenerationHelper.cs +++ b/src/StronglyTypedIds/SourceGenerationHelper.cs @@ -40,10 +40,22 @@ public static string CreateId( {"); } + var hasGenericParent = false; while (parentClass is { } parent) { + sb.Append(" "); + + if (!string.IsNullOrEmpty(parent.Modifiers)) + { + sb.Append(parent.Modifiers).Append(' '); + } + + if (parent.Modifiers.IndexOf("partial", StringComparison.Ordinal) == -1) + { + sb.Append("partial "); + } + sb - .Append(" partial ") .Append(parent.Keyword) .Append(' ') .Append(parent.Name) @@ -52,11 +64,15 @@ public static string CreateId( .AppendLine(@" {"); parentsCount++; + hasGenericParent |= parent.IsGeneric; parentClass = parent.Child; } - // TODO: can't add this if it's a generic class - sb.AppendLine(" [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))]"); + if (!hasGenericParent) + { + sb.AppendLine(" [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))]"); + sb.AppendLine(" [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))]"); + } sb.AppendLine(template); diff --git a/src/StronglyTypedIds/StronglyTypedIds.csproj b/src/StronglyTypedIds/StronglyTypedIds.csproj index 8e9d26610..95813be5f 100644 --- a/src/StronglyTypedIds/StronglyTypedIds.csproj +++ b/src/StronglyTypedIds/StronglyTypedIds.csproj @@ -12,6 +12,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -19,7 +23,7 @@ - + diff --git a/src/StronglyTypedIds/StructToGenerate.cs b/src/StronglyTypedIds/StructToGenerate.cs index f77083d20..af0596186 100644 --- a/src/StronglyTypedIds/StructToGenerate.cs +++ b/src/StronglyTypedIds/StructToGenerate.cs @@ -30,18 +30,9 @@ public StructToGenerate(string name, string nameSpace, Template template, Parent public ParentClass? Parent { get; } } -internal sealed record Result +internal sealed record Result(TValue Value, EquatableArray Errors) where TValue : IEquatable? { - public Result(TValue value, EquatableArray errors) - { - Value = value; - Errors = errors; - } - - public TValue Value { get; } - public EquatableArray Errors { get; } - public static Result<(TValue, bool)> Fail() => new((default!, false), EquatableArray.Empty); } @@ -63,4 +54,6 @@ public Defaults(Template template) public string? TemplateName { get; } public Template? Template { get; } -} \ No newline at end of file +} + +internal record ParentClass(string Modifiers, string Keyword, string Name, string Constraints, ParentClass? Child, bool IsGeneric); \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_DapperTypeHandler.cs b/src/StronglyTypedIds/Templates/Guid/Guid_DapperTypeHandler.cs index 7d94a235e..ef9fffd8c 100644 --- a/src/StronglyTypedIds/Templates/Guid/Guid_DapperTypeHandler.cs +++ b/src/StronglyTypedIds/Templates/Guid/Guid_DapperTypeHandler.cs @@ -1,18 +1,18 @@  - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler + public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler { - public override void SetValue(System.Data.IDbDataParameter parameter, TESTID value) + public override void SetValue(System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { parameter.Value = value.Value; } - public override TESTID Parse(object value) + public override PLACEHOLDERID Parse(object value) { return value switch { - System.Guid guidValue => new TESTID(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new TESTID(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to TESTID"), + System.Guid guidValue => new PLACEHOLDERID(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), }; } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_EfCoreValueConverter.cs b/src/StronglyTypedIds/Templates/Guid/Guid_EfCoreValueConverter.cs index 18e4d5d61..7b046f3c5 100644 --- a/src/StronglyTypedIds/Templates/Guid/Guid_EfCoreValueConverter.cs +++ b/src/StronglyTypedIds/Templates/Guid/Guid_EfCoreValueConverter.cs @@ -1,11 +1,11 @@  - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) : base( id => id.Value, - value => new TESTID(value), + value => new PLACEHOLDERID(value), mappingHints ) { } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_NewtonsoftJsonConverter.cs b/src/StronglyTypedIds/Templates/Guid/Guid_NewtonsoftJsonConverter.cs index 9b96b63b2..7e5c6446c 100644 --- a/src/StronglyTypedIds/Templates/Guid/Guid_NewtonsoftJsonConverter.cs +++ b/src/StronglyTypedIds/Templates/Guid/Guid_NewtonsoftJsonConverter.cs @@ -1,20 +1,20 @@  - class TESTIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter + class PLACEHOLDERIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter { public override bool CanConvert(System.Type objectType) { - return objectType == typeof(TESTID); + return objectType == typeof(PLACEHOLDERID); } public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { - var id = (TESTID)value; + var id = (PLACEHOLDERID)value; serializer.Serialize(writer, id.Value); } public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { var guid = serializer.Deserialize(reader); - return guid.HasValue ? new TESTID(guid.Value) : null; + return guid.HasValue ? new PLACEHOLDERID(guid.Value) : null; } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Int/Int_DapperTypeHandler.cs b/src/StronglyTypedIds/Templates/Int/Int_DapperTypeHandler.cs index 8e3dc42c9..b67809c70 100644 --- a/src/StronglyTypedIds/Templates/Int/Int_DapperTypeHandler.cs +++ b/src/StronglyTypedIds/Templates/Int/Int_DapperTypeHandler.cs @@ -1,19 +1,19 @@  - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler + public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler { - public override void SetValue(System.Data.IDbDataParameter parameter, TESTID value) + public override void SetValue(System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { parameter.Value = value.Value; } - public override TESTID Parse(object value) + public override PLACEHOLDERID Parse(object value) { return value switch { - int intValue => new TESTID(intValue), - long longValue when longValue < int.MaxValue => new TESTID((int)longValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new TESTID(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to TESTID"), + int intValue => new PLACEHOLDERID(intValue), + long longValue when longValue < int.MaxValue => new PLACEHOLDERID((int)longValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), }; } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Int/Int_EfCoreValueConverter.cs b/src/StronglyTypedIds/Templates/Int/Int_EfCoreValueConverter.cs index 2245e6cf1..0378d4d52 100644 --- a/src/StronglyTypedIds/Templates/Int/Int_EfCoreValueConverter.cs +++ b/src/StronglyTypedIds/Templates/Int/Int_EfCoreValueConverter.cs @@ -1,11 +1,11 @@  - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) : base( id => id.Value, - value => new TESTID(value), + value => new PLACEHOLDERID(value), mappingHints ) { } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Int/Int_NewtonsoftJsonConverter.cs b/src/StronglyTypedIds/Templates/Int/Int_NewtonsoftJsonConverter.cs index 56409d73b..b535cacfe 100644 --- a/src/StronglyTypedIds/Templates/Int/Int_NewtonsoftJsonConverter.cs +++ b/src/StronglyTypedIds/Templates/Int/Int_NewtonsoftJsonConverter.cs @@ -1,20 +1,20 @@  - class TESTIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter + class PLACEHOLDERIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter { public override bool CanConvert(System.Type objectType) { - return objectType == typeof(TESTID); + return objectType == typeof(PLACEHOLDERID); } public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { - var id = (TESTID)value; + var id = (PLACEHOLDERID)value; serializer.Serialize(writer, id.Value); } public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { var result = serializer.Deserialize(reader); - return result.HasValue ? new TESTID(result.Value) : null; + return result.HasValue ? new PLACEHOLDERID(result.Value) : null; } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/guid-full.typedid b/src/StronglyTypedIds/Templates/guid-full.typedid new file mode 100644 index 000000000..cd696822e --- /dev/null +++ b/src/StronglyTypedIds/Templates/guid-full.typedid @@ -0,0 +1,248 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public PLACEHOLDERID(global::System.Guid value) + { + Value = value; + } + + public static PLACEHOLDERID New() => new PLACEHOLDERID(global::System.Guid.NewGuid()); + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(global::System.Guid.Empty); + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new PLACEHOLDERID(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + global::System.Guid guidValue => new PLACEHOLDERID(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var guid = serializer.Deserialize(reader); + return guid.HasValue ? new PLACEHOLDERID(guid.Value) : null; + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/guid.typedid b/src/StronglyTypedIds/Templates/guid.typedid deleted file mode 100644 index f9156173c..000000000 --- a/src/StronglyTypedIds/Templates/guid.typedid +++ /dev/null @@ -1,69 +0,0 @@ - [System.ComponentModel.TypeConverter(typeof(TESTIDTypeConverter))] - readonly partial struct TESTID : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public TESTID(System.Guid value) - { - Value = value; - } - - public static TESTID New() => new TESTID(System.Guid.NewGuid()); - public static readonly TESTID Empty = new TESTID(System.Guid.Empty); - - public bool Equals(TESTID other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is TESTID other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); - public static bool operator !=(TESTID a, TESTID b) => !(a == b); - - public int CompareTo(TESTID other) => Value.CompareTo(other.Value); - - class TESTIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - System.Guid guidValue => new TESTID(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new TESTID(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is TESTID idValue) - { - if (destinationType == typeof(System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/int-full.typedid b/src/StronglyTypedIds/Templates/int-full.typedid new file mode 100644 index 000000000..f2dfcfce0 --- /dev/null +++ b/src/StronglyTypedIds/Templates/int-full.typedid @@ -0,0 +1,244 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public int Value { get; } + + public PLACEHOLDERID(int value) + { + Value = value; + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(0); + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + int intValue => new PLACEHOLDERID(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt32()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(int.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(int.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (int.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(int.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(int.Parse(input, provider)); +#else + => new(int.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { +#if NET7_0_OR_GREATER + if (int.TryParse(input, provider, out var guid)) +#else + if (int.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + int intValue => new PLACEHOLDERID(intValue), + long longValue when longValue < int.MaxValue => new PLACEHOLDERID((int)longValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var result = serializer.Deserialize(reader); + return result.HasValue ? new PLACEHOLDERID(result.Value) : null; + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/int.typedid b/src/StronglyTypedIds/Templates/int.typedid deleted file mode 100644 index 569d36875..000000000 --- a/src/StronglyTypedIds/Templates/int.typedid +++ /dev/null @@ -1,68 +0,0 @@ - [System.ComponentModel.TypeConverter(typeof(TESTIDTypeConverter))] - readonly partial struct TESTID : System.IComparable, System.IEquatable - { - public int Value { get; } - - public TESTID(int value) - { - Value = value; - } - - public static readonly TESTID Empty = new TESTID(0); - - public bool Equals(TESTID other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is TESTID other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); - public static bool operator !=(TESTID a, TESTID b) => !(a == b); - - public int CompareTo(TESTID other) => Value.CompareTo(other.Value); - - class TESTIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - int intValue => new TESTID(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new TESTID(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is TESTID idValue) - { - if (destinationType == typeof(int)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } \ No newline at end of file diff --git a/test/IntegrationLibraries.props b/test/IntegrationLibraries.props index 8ba7bf0b0..33b690855 100644 --- a/test/IntegrationLibraries.props +++ b/test/IntegrationLibraries.props @@ -11,6 +11,12 @@ + + + + + + diff --git a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs index 0ce1ce679..5362a6bbe 100644 --- a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs +++ b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs @@ -9,12 +9,12 @@ public static class DapperTypeHandlers [ModuleInitializer] public static void AddHandlers() { - SqlMapper.AddTypeHandler(new DapperGuidId.DapperTypeHandler()); - SqlMapper.AddTypeHandler(new DapperIntId.DapperTypeHandler()); - SqlMapper.AddTypeHandler(new DapperStringId.DapperTypeHandler()); - SqlMapper.AddTypeHandler(new DapperLongId.DapperTypeHandler()); - SqlMapper.AddTypeHandler(new DapperNullableStringId.DapperTypeHandler()); - SqlMapper.AddTypeHandler(new DapperNewIdId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new ConvertersGuidId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new ConvertersIntId.DapperTypeHandler()); + // SqlMapper.AddTypeHandler(new DapperStringId.DapperTypeHandler()); + // SqlMapper.AddTypeHandler(new DapperLongId.DapperTypeHandler()); + // SqlMapper.AddTypeHandler(new DapperNullableStringId.DapperTypeHandler()); + // SqlMapper.AddTypeHandler(new DapperNewIdId.DapperTypeHandler()); } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/DefaultIdTests.cs b/test/StronglyTypedIds.IntegrationTests/DefaultIdTests.cs index 83d4ca184..e850196bd 100644 --- a/test/StronglyTypedIds.IntegrationTests/DefaultIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/DefaultIdTests.cs @@ -71,20 +71,6 @@ public void CantCreateEmptyGeneratedId1() Assert.NotEqual((object)bar, (object)foo); } - [Fact] - public void WhenNoTypeConverter_SerializesWithValueProperty() - { - var foo = DefaultId1.New(); - - var newtonsoft = SystemTextJsonSerializer.Serialize(foo); - var systemText = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":\"" + foo.Value + "\"}"; - - Assert.Equal(expected, newtonsoft); - Assert.Equal(expected, systemText); - } - [Theory] [InlineData("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")] public void TypeConverter_CanConvertToAndFrom(string value) diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index f8fe47426..2a273ea10 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -1,49 +1,56 @@ +using System.ComponentModel; using System.Text.Json; using StronglyTypedIds; #nullable enable -namespace StronglyTypedIds.IntegrationTests.Types -{ - [StronglyTypedId] - partial struct DefaultId1 { } - - [StronglyTypedId] - public partial struct DefaultId2 { } - - [StronglyTypedId(Template.Guid)] - partial struct GuidId1 { } - - [StronglyTypedId(Template.Guid)] - public partial struct GuidId2 { } - - // [StronglyTypedId(Template.Int)] - // partial struct IntId { } - // - // [StronglyTypedId(Template.Long)] - // partial struct LongId { } - // - // [StronglyTypedId("newid")] - // partial struct NewIdId1 { } - // - // [StronglyTypedId("newid")] - // public partial struct NewIdId2 { } - // - // [StronglyTypedId(Template.NullableString)] - // partial struct NullableStringId { } - // - // [StronglyTypedId(Template.String)] - // partial struct StringId { } - - // public partial class SomeType where T : new() - // { - // public partial record NestedType - // { - // public partial struct MoreNesting - // { - // [StronglyTypedId] - // public partial struct VeryNestedIds - // { - // } - // } - // } - // } -} \ No newline at end of file +namespace StronglyTypedIds.IntegrationTests.Types; + +[StronglyTypedId] +partial struct DefaultId1 { } + +[StronglyTypedId] +public partial struct DefaultId2 { } + +[StronglyTypedId(Template.Guid)] +partial struct GuidId1 { } + +[StronglyTypedId("guid-full")] +partial struct ConvertersGuidId { } + +[StronglyTypedId(Template.Guid)] +public partial struct GuidId2 { } + +[StronglyTypedId(Template.Int)] +partial struct IntId { } + +[StronglyTypedId("int-full")] +partial struct ConvertersIntId { } +// +// [StronglyTypedId(Template.Long)] +// partial struct LongId { } + +[StronglyTypedId("newid")] +partial struct NewIdId1 { } + +[StronglyTypedId("newid")] +public partial struct NewIdId2 { } + +// [StronglyTypedId(Template.NullableString)] +// partial struct NullableStringId { } +// +// [StronglyTypedId(Template.String)] +// partial struct StringId { } +// +// public partial class SomeType where T : new() +// { +// public partial record struct NestedType +// { +// public partial struct MoreNesting +// { +// [StronglyTypedId] +// public readonly partial struct VeryNestedIds +// { +// } +// } +// } +// } +// diff --git a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs index bebbd570b..605914e46 100644 --- a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs @@ -77,7 +77,7 @@ public void CantCreateEmptyGeneratedId1() [Fact] public void CanSerializeToGuid_WithTypeConverter() { - var foo = NewtonsoftJsonGuidId.New(); + var foo = GuidId1.New(); var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); var serializedGuid = NewtonsoftJsonSerializer.SerializeObject(foo.Value); @@ -88,7 +88,7 @@ public void CanSerializeToGuid_WithTypeConverter() [Fact] public void CanSerializeToGuid_WithSystemTextJsonProvider() { - var foo = SystemTextJsonGuidId.New(); + var foo = GuidId1.New(); var serializedFoo = SystemTextJsonSerializer.Serialize(foo); var serializedGuid = SystemTextJsonSerializer.Serialize(foo.Value); @@ -97,72 +97,60 @@ public void CanSerializeToGuid_WithSystemTextJsonProvider() } [Fact] - public void CanDeserializeFromGuid_WithNewtonsoftJsonProvider() + public void CanDeserializeFromGuid_WithSystemTextJsonProvider() { var value = Guid.NewGuid(); - var foo = new NewtonsoftJsonGuidId(value); - var serializedGuid = NewtonsoftJsonSerializer.SerializeObject(value); + var foo = new GuidId1(value); + var serializedGuid = SystemTextJsonSerializer.Serialize(value); - var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedGuid); + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedGuid); Assert.Equal(foo, deserializedFoo); } + [Fact] + public void CanDeserializeFromGuid_WithNewtonsoftJsonProvider() + { + var value = Guid.NewGuid(); + var foo = new ConvertersGuidId(value); + var serializedGuid = NewtonsoftJsonSerializer.SerializeObject(value); + + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedGuid); + + Assert.Equal(foo, deserializedFoo); + } + [Fact] public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() { var entity = new EntityWithNullableId { Id = null }; - + var json = NewtonsoftJsonSerializer.SerializeObject(entity); var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); - + Assert.NotNull(deserialize); Assert.Null(deserialize.Id); } - [Fact] - public void CanDeserializeFromGuid_WithSystemTextJsonProvider() - { - var value = Guid.NewGuid(); - var foo = new SystemTextJsonGuidId(value); - var serializedGuid = SystemTextJsonSerializer.Serialize(value); - - var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedGuid); - - Assert.Equal(foo, deserializedFoo); - } - [Fact] public void CanSerializeToGuid_WithBothJsonConverters() { - var foo = BothJsonGuidId.New(); - + var foo = ConvertersGuidId.New(); + var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); var serializedGuid1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - + var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); var serializedGuid2 = SystemTextJsonSerializer.Serialize(foo.Value); - + Assert.Equal(serializedFoo1, serializedGuid1); Assert.Equal(serializedFoo2, serializedGuid2); } - [Fact] - public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() - { - var foo = NoJsonGuidId.New(); - - var serialized = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":\"" + foo.Value + "\"}"; - - Assert.Equal(expected, serialized); - } - [Fact] public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() { - var foo = NoJsonGuidId.New(); + var foo = GuidId1.New(); var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); @@ -171,35 +159,21 @@ public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() Assert.Equal(expected, serialized); } - [Fact] - public void WhenNoTypeConverter_SerializesWithValueProperty() - { - var foo = NoConverterGuidId.New(); - - var newtonsoft = SystemTextJsonSerializer.Serialize(foo); - var systemText = SystemTextJsonSerializer.Serialize(foo); - - var expected = "{\"Value\":\"" + foo.Value + "\"}"; - - Assert.Equal(expected, newtonsoft); - Assert.Equal(expected, systemText); - } - [Fact] public void WhenEfCoreValueConverterUsesValueConverter() { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); - + var options = new DbContextOptionsBuilder() .UseSqlite(connection) .Options; - + using (var context = new TestDbContext(options)) { context.Database.EnsureCreated(); context.Entities.Add( - new TestEntity { Id = EfCoreGuidId.New() }); + new TestEntity { Id = ConvertersGuidId.New() }); context.SaveChanges(); } using (var context = new TestDbContext(options)) @@ -214,21 +188,21 @@ public async Task WhenDapperValueConverterUsesValueConverter() { using var connection = new SqliteConnection("DataSource=:memory:"); await connection.OpenAsync(); - - var results = await connection.QueryAsync("SELECT '5640dad4-862a-4738-9e3c-c76dc227eb66'"); - + + var results = await connection.QueryAsync("SELECT '5640dad4-862a-4738-9e3c-c76dc227eb66'"); + var value = Assert.Single(results); - Assert.Equal(value, new DapperGuidId(Guid.Parse("5640dad4-862a-4738-9e3c-c76dc227eb66"))); + Assert.Equal(value, new ConvertersGuidId(Guid.Parse("5640dad4-862a-4738-9e3c-c76dc227eb66"))); } [Theory] [InlineData("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")] public void TypeConverter_CanConvertToAndFrom(string value) { - var converter = TypeDescriptor.GetConverter(typeof(NoJsonGuidId)); + var converter = TypeDescriptor.GetConverter(typeof(GuidId1)); var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new NoJsonGuidId(Guid.Parse(value)), id); + Assert.IsType(id); + Assert.Equal(new GuidId1(Guid.Parse(value)), id); var reconverted = converter.ConvertTo(id, value.GetType()); Assert.Equal(value, reconverted); @@ -237,8 +211,8 @@ public void TypeConverter_CanConvertToAndFrom(string value) [Fact] public void CanCompareDefaults() { - ComparableGuidId original = default; - var other = ComparableGuidId.Empty; + GuidId1 original = default; + var other = GuidId1.Empty; var compare1 = original.CompareTo(other); var compare2 = other.CompareTo(original); @@ -248,11 +222,11 @@ public void CanCompareDefaults() [Fact] public void CanEquateDefaults() { - EquatableGuidId original = default; - var other = EquatableGuidId.Empty; + GuidId1 original = default; + var other = GuidId1.Empty; - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); Assert.Equal(equals1, equals2); } @@ -260,100 +234,117 @@ public void CanEquateDefaults() [Fact] public void ImplementsInterfaces() { - Assert.IsAssignableFrom>(BothGuidId.Empty); - Assert.IsAssignableFrom>(BothGuidId.Empty); - - Assert.IsAssignableFrom>(EquatableGuidId.Empty); - Assert.IsAssignableFrom>(ComparableGuidId.Empty); - + Assert.IsAssignableFrom>(GuidId1.Empty); + Assert.IsAssignableFrom>(GuidId1.Empty); + Assert.IsAssignableFrom(GuidId1.Empty); + +#pragma warning disable CS0183 #pragma warning disable 184 - Assert.False(GuidId1.Empty is IComparable); - Assert.False(GuidId1.Empty is IEquatable); + Assert.True(GuidId1.Empty is IComparable); + Assert.True(GuidId1.Empty is IEquatable); #pragma warning restore 184 +#pragma warning restore CS0183 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(GuidId1.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs(Guid.NewGuid().ToString()); + ParseSpan(Guid.NewGuid().ToString().AsSpan()); + + T ParseAs(string s) where T: IParsable { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T: ISpanParsable { + return T.Parse(s, null); + } +#endif + } + +#if NET6_0_OR_GREATER + [Fact] + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add( + new TestEntity { Id = ConvertersGuidId.New() }); + context.SaveChanges(); + } + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + Assert.Single(all); + } + } + + internal class ConventionsDbContext : DbContext + { + public DbSet Entities { get; set; } + + public ConventionsDbContext(DbContextOptions options) : base(options) + { + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + configurationBuilder + .Properties() + .HaveConversion(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); + } + } +#endif + + internal class TestDbContext : DbContext + { + public DbSet Entities { get; set; } + + public TestDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .HasConversion(new ConvertersGuidId.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); + } + } + + internal class TestEntity + { + public ConvertersGuidId Id { get; set; } + } + + internal class EntityWithNullableId + { + public ConvertersGuidId? Id { get; set; } } -// -// #if NET6_0_OR_GREATER -// [Fact] -// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() -// { -// var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// using (var context = new ConventionsDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add( -// new TestEntity { Id = EfCoreGuidId.New() }); -// context.SaveChanges(); -// } -// using (var context = new ConventionsDbContext(options)) -// { -// var all = context.Entities.ToList(); -// Assert.Single(all); -// } -// } -// -// public class ConventionsDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public ConventionsDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) -// { -// configurationBuilder -// .Properties() -// .HaveConversion(); -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .ValueGeneratedNever(); -// }); -// } -// } -// #endif -// -// public class TestDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public TestDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .HasConversion(new EfCoreGuidId.EfCoreValueConverter()) -// .ValueGeneratedNever(); -// }); -// } -// } -// -// public class TestEntity -// { -// public EfCoreGuidId Id { get; set; } -// } -// -// public class EntityWithNullableId -// { -// public NewtonsoftJsonGuidId? Id { get; set; } -// } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs index 24bed3950..24ce6dcce 100644 --- a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs @@ -1,352 +1,330 @@ -// using System; -// using System.ComponentModel; -// using System.Linq; -// using System.Threading.Tasks; -// using Dapper; -// using Microsoft.Data.Sqlite; -// using Microsoft.EntityFrameworkCore; -// using StronglyTypedIds.IntegrationTests.Types; -// using Xunit; -// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; -// -// namespace StronglyTypedIds.IntegrationTests -// { -// public class IntIdTests -// { -// [Fact] -// public void SameValuesAreEqual() -// { -// var id = 123; -// var foo1 = new IntId(id); -// var foo2 = new IntId(id); -// -// Assert.Equal(foo1, foo2); -// } -// -// [Fact] -// public void EmptyValueIsEmpty() -// { -// Assert.Equal(0, IntId.Empty.Value); -// } -// -// -// [Fact] -// public void DifferentValuesAreUnequal() -// { -// var foo1 = new IntId(1); -// var foo2 = new IntId(2); -// -// Assert.NotEqual(foo1, foo2); -// } -// -// [Fact] -// public void OverloadsWorkCorrectly() -// { -// var id = 12; -// var same1 = new IntId(id); -// var same2 = new IntId(id); -// var different = new IntId(3); -// -// Assert.True(same1 == same2); -// Assert.False(same1 == different); -// Assert.False(same1 != same2); -// Assert.True(same1 != different); -// } -// -// [Fact] -// public void DifferentTypesAreUnequal() -// { -// var bar = GuidId2.New(); -// var foo = new IntId(23); -// -// //Assert.NotEqual(bar, foo); // does not compile -// Assert.NotEqual((object)bar, (object)foo); -// } -// -// [Fact] -// public void CanSerializeToInt_WithNewtonsoftJsonProvider() -// { -// var foo = new NewtonsoftJsonIntId(123); -// -// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedInt = NewtonsoftJsonSerializer.SerializeObject(foo.Value); -// -// Assert.Equal(serializedFoo, serializedInt); -// } -// -// [Fact] -// public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() -// { -// var entity = new EntityWithNullableId { Id = null }; -// -// var json = NewtonsoftJsonSerializer.SerializeObject(entity); -// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); -// -// Assert.NotNull(deserialize); -// Assert.Null(deserialize.Id); -// } -// -// [Fact] -// public void CanSerializeToInt_WithSystemTextJsonProvider() -// { -// var foo = new SystemTextJsonIntId(123); -// -// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); -// var serializedInt = SystemTextJsonSerializer.Serialize(foo.Value); -// -// Assert.Equal(serializedFoo, serializedInt); -// } -// -// [Fact] -// public void CanDeserializeFromInt_WithNewtonsoftJsonProvider() -// { -// var value = 123; -// var foo = new NewtonsoftJsonIntId(value); -// var serializedInt = NewtonsoftJsonSerializer.SerializeObject(value); -// -// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedInt); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanDeserializeFromInt_WithSystemTextJsonProvider() -// { -// var value = 123; -// var foo = new SystemTextJsonIntId(value); -// var serializedInt = SystemTextJsonSerializer.Serialize(value); -// -// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedInt); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanSerializeToInt_WithBothJsonConverters() -// { -// var foo = new BothJsonIntId(123); -// -// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedInt1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); -// -// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); -// var serializedInt2 = SystemTextJsonSerializer.Serialize(foo.Value); -// -// Assert.Equal(serializedFoo1, serializedInt1); -// Assert.Equal(serializedFoo2, serializedInt2); -// } -// -// [Fact] -// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() -// { -// var foo = new NoJsonIntId(123); -// -// var serialized = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":" + foo.Value + "}"; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() -// { -// var foo = new NoJsonIntId(123); -// -// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); -// -// var expected = $"\"{foo.Value}\""; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoTypeConverter_SerializesWithValueProperty() -// { -// var foo = new NoConverterIntId(123); -// -// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); -// var systemText = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":" + foo.Value + "}"; -// -// Assert.Equal(expected, newtonsoft); -// Assert.Equal(expected, systemText); -// } -// -// [Fact] -// public void WhenEfCoreValueConverterUsesValueConverter() -// { -// var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// var original = new TestEntity { Id = new EfCoreIntId(123) }; -// using (var context = new TestDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add(original); -// context.SaveChanges(); -// } -// using (var context = new TestDbContext(options)) -// { -// var all = context.Entities.ToList(); -// var retrieved = Assert.Single(all); -// Assert.Equal(original.Id, retrieved.Id); -// } -// } -// -// [Fact] -// public async Task WhenDapperValueConverterUsesValueConverter() -// { -// using var connection = new SqliteConnection("DataSource=:memory:"); -// await connection.OpenAsync(); -// -// var results = await connection.QueryAsync("SELECT 123"); -// -// var value = Assert.Single(results); -// Assert.Equal(new DapperIntId(123), value); -// } -// -// [Theory] -// [InlineData(123)] -// [InlineData("123")] -// public void TypeConverter_CanConvertToAndFrom(object value) -// { -// var converter = TypeDescriptor.GetConverter(typeof(NoJsonIntId)); -// var id = converter.ConvertFrom(value); -// Assert.IsType(id); -// Assert.Equal(new NoJsonIntId(123), id); -// -// var reconverted = converter.ConvertTo(id, value.GetType()); -// Assert.Equal(value, reconverted); -// } -// -// [Fact] -// public void CanCompareDefaults() -// { -// ComparableIntId original = default; -// var other = ComparableIntId.Empty; -// -// var compare1 = original.CompareTo(other); -// var compare2 = other.CompareTo(original); -// Assert.Equal(compare1, -compare2); -// } -// -// [Fact] -// public void CanEquateDefaults() -// { -// EquatableIntId original = default; -// var other = EquatableIntId.Empty; -// -// var equals1 = (original as IEquatable).Equals(other); -// var equals2 = (other as IEquatable).Equals(original); -// -// Assert.Equal(equals1, equals2); -// } -// -// [Fact] -// public void ImplementsInterfaces() -// { -// Assert.IsAssignableFrom>(BothIntId.Empty); -// Assert.IsAssignableFrom>(BothIntId.Empty); -// -// Assert.IsAssignableFrom>(EquatableIntId.Empty); -// Assert.IsAssignableFrom>(ComparableIntId.Empty); -// -// #pragma warning disable 184 -// Assert.False(IntId.Empty is IComparable); -// Assert.False(IntId.Empty is IEquatable); -// #pragma warning restore 184 -// } -// -// -// #if NET6_0_OR_GREATER -// [Fact] -// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() -// { -// var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// using (var context = new ConventionsDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add( -// new TestEntity { Id = new EfCoreIntId(123) }); -// context.SaveChanges(); -// } -// using (var context = new ConventionsDbContext(options)) -// { -// var all = context.Entities.ToList(); -// Assert.Single(all); -// } -// } -// -// public class ConventionsDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public ConventionsDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) -// { -// configurationBuilder -// .Properties() -// .HaveConversion(); -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .ValueGeneratedNever(); -// }); -// } -// } -// #endif -// -// public class TestDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public TestDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .HasConversion(new EfCoreIntId.EfCoreValueConverter()) -// .ValueGeneratedNever(); -// }); -// } -// } -// -// public class TestEntity -// { -// public EfCoreIntId Id { get; set; } -// } -// -// public class EntityWithNullableId -// { -// public NewtonsoftJsonIntId? Id { get; set; } -// } -// } -// } \ No newline at end of file +using System; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; +using Dapper; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using StronglyTypedIds.IntegrationTests.Types; +using Xunit; +using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; + +namespace StronglyTypedIds.IntegrationTests; + +public class IntIdTests +{ + [Fact] + public void SameValuesAreEqual() + { + var id = 123; + var foo1 = new IntId(id); + var foo2 = new IntId(id); + + Assert.Equal(foo1, foo2); + } + + [Fact] + public void EmptyValueIsEmpty() + { + Assert.Equal(0, IntId.Empty.Value); + } + + + [Fact] + public void DifferentValuesAreUnequal() + { + var foo1 = new IntId(1); + var foo2 = new IntId(2); + + Assert.NotEqual(foo1, foo2); + } + + [Fact] + public void OverloadsWorkCorrectly() + { + var id = 12; + var same1 = new IntId(id); + var same2 = new IntId(id); + var different = new IntId(3); + + Assert.True(same1 == same2); + Assert.False(same1 == different); + Assert.False(same1 != same2); + Assert.True(same1 != different); + } + + [Fact] + public void DifferentTypesAreUnequal() + { + var bar = GuidId2.New(); + var foo = new IntId(23); + + //Assert.NotEqual(bar, foo); // does not compile + Assert.NotEqual((object) bar, (object) foo); + } + + [Fact] + public void CanSerializeToInt_WithNewtonsoftJsonProvider() + { + var foo = new ConvertersIntId(123); + + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedInt = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + Assert.Equal(serializedFoo, serializedInt); + } + + [Fact] + public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() + { + var entity = new EntityWithNullableId {Id = null}; + + var json = NewtonsoftJsonSerializer.SerializeObject(entity); + var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); + + Assert.NotNull(deserialize); + Assert.Null(deserialize.Id); + } + + [Fact] + public void CanSerializeToInt_WithSystemTextJsonProvider() + { + var foo = new ConvertersIntId(123); + + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedInt = SystemTextJsonSerializer.Serialize(foo.Value); + + Assert.Equal(serializedFoo, serializedInt); + } + + [Fact] + public void CanDeserializeFromInt_WithNewtonsoftJsonProvider() + { + var value = 123; + var foo = new ConvertersIntId(value); + var serializedInt = NewtonsoftJsonSerializer.SerializeObject(value); + + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedInt); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void CanDeserializeFromInt_WithSystemTextJsonProvider() + { + var value = 123; + var foo = new ConvertersIntId(value); + var serializedInt = SystemTextJsonSerializer.Serialize(value); + + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedInt); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() + { + var foo = new IntId(123); + + var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); + + var expected = $"\"{foo.Value}\""; + + Assert.Equal(expected, serialized); + } + + [Fact] + public void WhenEfCoreValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity {Id = new ConvertersIntId(123)}; + using (var context = new TestDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add(original); + context.SaveChanges(); + } + + using (var context = new TestDbContext(options)) + { + var all = context.Entities.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); + } + } + + [Fact] + public async Task WhenDapperValueConverterUsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + await connection.OpenAsync(); + + var results = await connection.QueryAsync("SELECT 123"); + + var value = Assert.Single(results); + Assert.Equal(new ConvertersIntId(123), value); + } + + [Theory] + [InlineData(123)] + [InlineData("123")] + public void TypeConverter_CanConvertToAndFrom(object value) + { + var converter = TypeDescriptor.GetConverter(typeof(ConvertersIntId)); + var id = converter.ConvertFrom(value); + Assert.IsType(id); + Assert.Equal(new ConvertersIntId(123), id); + + var reconverted = converter.ConvertTo(id, value.GetType()); + Assert.Equal(value, reconverted); + } + + [Fact] + public void CanCompareDefaults() + { + IntId original = default; + var other = IntId.Empty; + + var compare1 = original.CompareTo(other); + var compare2 = other.CompareTo(original); + Assert.Equal(compare1, -compare2); + } + + [Fact] + public void CanEquateDefaults() + { + IntId original = default; + var other = IntId.Empty; + + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); + + Assert.Equal(equals1, equals2); + } + + [Fact] + public void ImplementsInterfaces() + { + Assert.IsAssignableFrom>(IntId.Empty); + Assert.IsAssignableFrom>(IntId.Empty); + Assert.IsAssignableFrom(IntId.Empty); + +#pragma warning disable CS0183 +#pragma warning disable 184 + Assert.True(IntId.Empty is IComparable); + Assert.True(IntId.Empty is IEquatable); +#pragma warning restore 184 +#pragma warning restore CS0183 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(IntId.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs("123"); + ParseSpan("123".AsSpan()); + + T ParseAs(string s) where T : IParsable + { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + { + return T.Parse(s, null); + } +#endif + } + +#if NET6_0_OR_GREATER + [Fact] + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add( + new TestEntity {Id = new ConvertersIntId(123)}); + context.SaveChanges(); + } + + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + Assert.Single(all); + } + } + + internal class ConventionsDbContext : DbContext + { + public DbSet Entities { get; set; } + + public ConventionsDbContext(DbContextOptions options) : base(options) + { + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + configurationBuilder + .Properties() + .HaveConversion(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); + } + } +#endif + + internal class TestDbContext : DbContext + { + public DbSet Entities { get; set; } + + public TestDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .HasConversion(new ConvertersIntId.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); + } + } + + internal class TestEntity + { + public ConvertersIntId Id { get; set; } + } + + internal class EntityWithNullableId + { + public ConvertersIntId? Id { get; set; } + } +} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj b/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj index 3e31d5834..6ff0daea3 100644 --- a/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj +++ b/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj @@ -14,6 +14,7 @@ + diff --git a/test/StronglyTypedIds.Tests/EmbeddedResourceTests.cs b/test/StronglyTypedIds.Tests/EmbeddedResourceTests.cs index 4a13cec27..412c6c8ab 100644 --- a/test/StronglyTypedIds.Tests/EmbeddedResourceTests.cs +++ b/test/StronglyTypedIds.Tests/EmbeddedResourceTests.cs @@ -14,6 +14,7 @@ public class EmbeddedResourceTests "StronglyTypedIdBackingType", "StronglyTypedIdConverter", "StronglyTypedIdImplementations", + "Template", }; [Theory] diff --git a/test/StronglyTypedIds.Tests/EqualityTests.cs b/test/StronglyTypedIds.Tests/EqualityTests.cs index f7db52c62..6260cbbb9 100644 --- a/test/StronglyTypedIds.Tests/EqualityTests.cs +++ b/test/StronglyTypedIds.Tests/EqualityTests.cs @@ -17,7 +17,7 @@ public void ParentClassHasExpectedEqualityBehaviour() Assert.True(instance1.Equals(instance2)); Assert.True(instance1 == instance2); - ParentClass GetParentClass() => new("struct", "TestName", "where T : class", null); + ParentClass GetParentClass() => new(null, "struct", "TestName", "where T : class", null, false); } [Fact] @@ -30,7 +30,7 @@ public void ParentClassWithParentHasExpectedEqualityBehaviour() Assert.True(instance1.Equals(instance2)); Assert.True(instance1 == instance2); - ParentClass GetParentClass() => new("struct", "TestName", "where T : class", new ParentClass("class", "b", "", null)); + ParentClass GetParentClass() => new(null, "struct", "TestName", "where T : class", new ParentClass(null, "class", "b", "", null, false), false); } [Fact] @@ -67,7 +67,7 @@ StructToGenerate GetStruct() name: "MyStruct", nameSpace: "MyNamespace", templateName: "Guid", - parent: new ParentClass("class", "b", "", null)); + parent: new ParentClass(null, "class", "b", "", null, false)); } } @@ -87,7 +87,7 @@ public void ResultWithoutDiagnosticHasExpectedEqualityBehaviour() name: "MyStruct", nameSpace: "MyNamespace", templateName: "Guid", - parent: new ParentClass("class", "b", "", null)); + parent: new ParentClass(null, "class", "b", "", null, false)); return new Result<(StructToGenerate, bool)>((instance, true), new EquatableArray()); } @@ -109,7 +109,7 @@ public void ResultWithDiagnosticHasExpectedEqualityBehaviour() name: "MyStruct", nameSpace: "MyNamespace", templateName: "Guid", - parent: new ParentClass("class", "b", "", null)); + parent: new ParentClass(null, "class", "b", "", null, false)); var diagnostics = new DiagnosticInfo(new DiagnosticDescriptor( InvalidBackingTypeDiagnostic.Id, InvalidBackingTypeDiagnostic.Title, InvalidBackingTypeDiagnostic.Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt new file mode 100644 index 000000000..c505a45d2 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt @@ -0,0 +1,31 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Guid.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Guid.verified.txt deleted file mode 100644 index d7a3ed3e7..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Guid.verified.txt +++ /dev/null @@ -1,143 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) => Value.CompareTo(other.Value); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new MyTestId(value), - mappingHints - ) { } - } - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - System.Guid guidValue => new MyTestId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyTestId(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - System.Guid guidValue => new MyTestId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyTestId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyTestId(guid.Value) : null; - } - } - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Int.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Int.verified.txt deleted file mode 100644 index e7affbacb..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Int.verified.txt +++ /dev/null @@ -1,143 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId : System.IComparable, System.IEquatable - { - public int Value { get; } - - public MyTestId(int value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) => Value.CompareTo(other.Value); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new MyTestId(value), - mappingHints - ) { } - } - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - int intValue => new MyTestId(intValue), - long longValue when longValue < int.MaxValue => new MyTestId((int)longValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyTestId(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - int intValue => new MyTestId(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyTestId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(int)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var result = serializer.Deserialize(reader); - return result.HasValue ? new MyTestId(result.Value) : null; - } - } - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(reader.GetInt32()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteNumberValue(value.Value); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Long.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Long.verified.txt deleted file mode 100644 index 0a464e952..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=Long.verified.txt +++ /dev/null @@ -1,146 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId : System.IComparable, System.IEquatable - { - public long Value { get; } - - public MyTestId(long value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) => Value.CompareTo(other.Value); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new MyTestId(value), - mappingHints - ) { } - } - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - long longValue => new MyTestId(longValue), - int intValue => new MyTestId(intValue), - short shortValue => new MyTestId(shortValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new MyTestId(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(long) || sourceType == typeof(int) || sourceType == typeof(short) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - long longValue => new MyTestId(longValue), - int intValue => new MyTestId(intValue), - short shortValue => new MyTestId(shortValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new MyTestId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(long)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var result = serializer.Deserialize(reader); - return result.HasValue ? new MyTestId(result.Value) : null; - } - } - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(reader.GetInt64()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteNumberValue(value.Value); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=MassTransitNewId.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=MassTransitNewId.verified.txt deleted file mode 100644 index c2c044246..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=MassTransitNewId.verified.txt +++ /dev/null @@ -1,151 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId : System.IComparable, System.IEquatable - { - public MassTransit.NewId Value { get; } - - public MyTestId(MassTransit.NewId value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(MassTransit.NewId.Next()); - public static readonly MyTestId Empty = new MyTestId(MassTransit.NewId.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) => Value.CompareTo(other.Value); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value.ToGuid(), - value => new MyTestId(MassTransit.NewId.FromGuid(value)), - mappingHints - ) { } - } - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value.ToGuid(); - } - - public override MyTestId Parse(object value) - { - return value switch - { - System.Guid guidValue => new MyTestId(MassTransit.NewId.FromGuid(guidValue)), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyTestId(MassTransit.NewId.FromGuid(result)), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || - sourceType == typeof(string) || base.CanConvertFrom - (context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - MassTransit.NewId newIdValue => new MyTestId(newIdValue), - System.Guid guidValue => new MyTestId(MassTransit.NewId.FromGuid(guidValue)), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyTestId(MassTransit.NewId.FromGuid(result)), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(MassTransit.NewId)) - { - return idValue.Value; - } - - if (destinationType == typeof(System.Guid)) - { - return idValue.Value.ToGuid(); - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToGuid().ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value.ToGuid()); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyTestId(MassTransit.NewId.FromGuid(guid.Value)) : null; - } - } - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(MassTransit.NewId.FromGuid(reader.GetGuid())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value.ToGuid()); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=NullableString.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=NullableString.verified.txt deleted file mode 100644 index 975c29ade..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=NullableString.verified.txt +++ /dev/null @@ -1,175 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId : System.IComparable, System.IEquatable - { - public string? Value { get; } - - public MyTestId(string? value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => 0, - (null, _) => -1, - (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), - }; - } - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) - : base( - id => id.Value!, - value => new MyTestId(value), - mappingHints - ) { } - } - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - null => new MyTestId(null), - System.DBNull => new MyTestId(null), - string stringValue => new MyTestId(stringValue), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) - { - if (value is null) - { - return new MyTestId(null); - } - - var stringValue = value as string; - if (stringValue is not null) - { - return new MyTestId(stringValue); - } - - return base.ConvertFrom(context, culture, value); - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Type? sourceType) - { - return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(string)) - { - return idValue.Value; - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object? value, Newtonsoft.Json.JsonSerializer serializer) - { - if (value is null) - { - serializer.Serialize(writer, null); - } - else - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - return new MyTestId(serializer.Deserialize(reader)); - } - } - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(reader.GetString()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - if (value.Value is null) - { - writer.WriteNullValue(); - } - else - { - writer.WriteStringValue(value.Value); - } - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=String.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=String.verified.txt deleted file mode 100644 index 3e93ee6b2..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFullIdCorrectly_type=String.verified.txt +++ /dev/null @@ -1,161 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId : System.IComparable, System.IEquatable - { - public string Value { get; } - - public MyTestId(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => 0, - (null, _) => -1, - (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), - }; - } - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new MyTestId(value), - mappingHints - ) { } - } - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - string stringValue => new MyTestId(stringValue), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - var stringValue = value as string; - if (stringValue is not null) - { - return new MyTestId(stringValue); - } - - return base.ConvertFrom(context, culture, value); - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(string)) - { - return idValue.Value; - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - if (objectType == typeof(MyTestId?)) - { - var value = serializer.Deserialize(reader); - - return value is null ? null : new MyTestId(value); - } - - return new MyTestId(serializer.Deserialize(reader)); - } - } - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(reader.GetString()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=DapperTypeHandler_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=DapperTypeHandler_i=None.verified.txt deleted file mode 100644 index bb6b344ab..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=DapperTypeHandler_i=None.verified.txt +++ /dev/null @@ -1,54 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - System.Guid guidValue => new MyTestId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyTestId(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=EfCoreValueConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=EfCoreValueConverter_i=None.verified.txt deleted file mode 100644 index 508208c37..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=EfCoreValueConverter_i=None.verified.txt +++ /dev/null @@ -1,47 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new MyTestId(value), - mappingHints - ) { } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=NewtonsoftJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=NewtonsoftJson_i=None.verified.txt deleted file mode 100644 index db59f66c1..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=NewtonsoftJson_i=None.verified.txt +++ /dev/null @@ -1,57 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - readonly partial struct MyTestId - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyTestId(guid.Value) : null; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=IComparable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=IComparable.verified.txt deleted file mode 100644 index bef90429e..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=IComparable.verified.txt +++ /dev/null @@ -1,37 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IComparable - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) => Value.CompareTo(other.Value); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=IEquatable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=IEquatable.verified.txt deleted file mode 100644 index a13e9bec6..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=IEquatable.verified.txt +++ /dev/null @@ -1,36 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IEquatable - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=None.verified.txt deleted file mode 100644 index fad5ea0b5..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=None_i=None.verified.txt +++ /dev/null @@ -1,36 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=SystemTextJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=SystemTextJson_i=None.verified.txt deleted file mode 100644 index d6d801a99..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=SystemTextJson_i=None.verified.txt +++ /dev/null @@ -1,50 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - readonly partial struct MyTestId - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=TypeConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=TypeConverter_i=None.verified.txt deleted file mode 100644 index 295e92baf..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Guid_c=TypeConverter_i=None.verified.txt +++ /dev/null @@ -1,78 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - System.Guid guidValue => new MyTestId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyTestId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=DapperTypeHandler_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=DapperTypeHandler_i=None.verified.txt deleted file mode 100644 index f8d24bbf5..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=DapperTypeHandler_i=None.verified.txt +++ /dev/null @@ -1,54 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public int Value { get; } - - public MyTestId(int value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - int intValue => new MyTestId(intValue), - long longValue when longValue < int.MaxValue => new MyTestId((int)longValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyTestId(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=EfCoreValueConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=EfCoreValueConverter_i=None.verified.txt deleted file mode 100644 index d3e50467b..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=EfCoreValueConverter_i=None.verified.txt +++ /dev/null @@ -1,46 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public int Value { get; } - - public MyTestId(int value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new MyTestId(value), - mappingHints - ) { } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=NewtonsoftJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=NewtonsoftJson_i=None.verified.txt deleted file mode 100644 index b4d9738e7..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=NewtonsoftJson_i=None.verified.txt +++ /dev/null @@ -1,56 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - readonly partial struct MyTestId - { - public int Value { get; } - - public MyTestId(int value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var result = serializer.Deserialize(reader); - return result.HasValue ? new MyTestId(result.Value) : null; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=IComparable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=IComparable.verified.txt deleted file mode 100644 index d76d3afd2..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=IComparable.verified.txt +++ /dev/null @@ -1,36 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IComparable - { - public int Value { get; } - - public MyTestId(int value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) => Value.CompareTo(other.Value); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=IEquatable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=IEquatable.verified.txt deleted file mode 100644 index 5d23b64a1..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=IEquatable.verified.txt +++ /dev/null @@ -1,35 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IEquatable - { - public int Value { get; } - - public MyTestId(int value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=None.verified.txt deleted file mode 100644 index 45272d34a..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=None_i=None.verified.txt +++ /dev/null @@ -1,35 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public int Value { get; } - - public MyTestId(int value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=SystemTextJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=SystemTextJson_i=None.verified.txt deleted file mode 100644 index 7c016c3be..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=SystemTextJson_i=None.verified.txt +++ /dev/null @@ -1,49 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - readonly partial struct MyTestId - { - public int Value { get; } - - public MyTestId(int value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(reader.GetInt32()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteNumberValue(value.Value); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=TypeConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=TypeConverter_i=None.verified.txt deleted file mode 100644 index 39f1e9331..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Int_c=TypeConverter_i=None.verified.txt +++ /dev/null @@ -1,77 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId - { - public int Value { get; } - - public MyTestId(int value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - int intValue => new MyTestId(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyTestId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(int)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=DapperTypeHandler_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=DapperTypeHandler_i=None.verified.txt deleted file mode 100644 index 35fd482b5..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=DapperTypeHandler_i=None.verified.txt +++ /dev/null @@ -1,55 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public long Value { get; } - - public MyTestId(long value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - long longValue => new MyTestId(longValue), - int intValue => new MyTestId(intValue), - short shortValue => new MyTestId(shortValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new MyTestId(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=EfCoreValueConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=EfCoreValueConverter_i=None.verified.txt deleted file mode 100644 index cb5754863..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=EfCoreValueConverter_i=None.verified.txt +++ /dev/null @@ -1,46 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public long Value { get; } - - public MyTestId(long value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new MyTestId(value), - mappingHints - ) { } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=NewtonsoftJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=NewtonsoftJson_i=None.verified.txt deleted file mode 100644 index 7052a3b27..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=NewtonsoftJson_i=None.verified.txt +++ /dev/null @@ -1,56 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - readonly partial struct MyTestId - { - public long Value { get; } - - public MyTestId(long value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var result = serializer.Deserialize(reader); - return result.HasValue ? new MyTestId(result.Value) : null; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=IComparable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=IComparable.verified.txt deleted file mode 100644 index c38fa63f6..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=IComparable.verified.txt +++ /dev/null @@ -1,36 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IComparable - { - public long Value { get; } - - public MyTestId(long value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) => Value.CompareTo(other.Value); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=IEquatable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=IEquatable.verified.txt deleted file mode 100644 index 13b9b1ac7..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=IEquatable.verified.txt +++ /dev/null @@ -1,35 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IEquatable - { - public long Value { get; } - - public MyTestId(long value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=None.verified.txt deleted file mode 100644 index af1658c35..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=None_i=None.verified.txt +++ /dev/null @@ -1,35 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public long Value { get; } - - public MyTestId(long value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=SystemTextJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=SystemTextJson_i=None.verified.txt deleted file mode 100644 index 17a45333f..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=SystemTextJson_i=None.verified.txt +++ /dev/null @@ -1,49 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - readonly partial struct MyTestId - { - public long Value { get; } - - public MyTestId(long value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(reader.GetInt64()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteNumberValue(value.Value); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=TypeConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=TypeConverter_i=None.verified.txt deleted file mode 100644 index e22d0478c..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=Long_c=TypeConverter_i=None.verified.txt +++ /dev/null @@ -1,79 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId - { - public long Value { get; } - - public MyTestId(long value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(0); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(long) || sourceType == typeof(int) || sourceType == typeof(short) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - long longValue => new MyTestId(longValue), - int intValue => new MyTestId(intValue), - short shortValue => new MyTestId(shortValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new MyTestId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(long)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=DapperTypeHandler_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=DapperTypeHandler_i=None.verified.txt deleted file mode 100644 index 23efe4b09..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=DapperTypeHandler_i=None.verified.txt +++ /dev/null @@ -1,54 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public MassTransit.NewId Value { get; } - - public MyTestId(MassTransit.NewId value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(MassTransit.NewId.Next()); - public static readonly MyTestId Empty = new MyTestId(MassTransit.NewId.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value.ToGuid(); - } - - public override MyTestId Parse(object value) - { - return value switch - { - System.Guid guidValue => new MyTestId(MassTransit.NewId.FromGuid(guidValue)), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyTestId(MassTransit.NewId.FromGuid(result)), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=EfCoreValueConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=EfCoreValueConverter_i=None.verified.txt deleted file mode 100644 index 9114f2d54..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=EfCoreValueConverter_i=None.verified.txt +++ /dev/null @@ -1,47 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public MassTransit.NewId Value { get; } - - public MyTestId(MassTransit.NewId value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(MassTransit.NewId.Next()); - public static readonly MyTestId Empty = new MyTestId(MassTransit.NewId.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value.ToGuid(), - value => new MyTestId(MassTransit.NewId.FromGuid(value)), - mappingHints - ) { } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=NewtonsoftJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=NewtonsoftJson_i=None.verified.txt deleted file mode 100644 index 181d85e44..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=NewtonsoftJson_i=None.verified.txt +++ /dev/null @@ -1,57 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - readonly partial struct MyTestId - { - public MassTransit.NewId Value { get; } - - public MyTestId(MassTransit.NewId value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(MassTransit.NewId.Next()); - public static readonly MyTestId Empty = new MyTestId(MassTransit.NewId.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value.ToGuid()); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyTestId(MassTransit.NewId.FromGuid(guid.Value)) : null; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=IComparable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=IComparable.verified.txt deleted file mode 100644 index 3a19fc65e..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=IComparable.verified.txt +++ /dev/null @@ -1,37 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IComparable - { - public MassTransit.NewId Value { get; } - - public MyTestId(MassTransit.NewId value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(MassTransit.NewId.Next()); - public static readonly MyTestId Empty = new MyTestId(MassTransit.NewId.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) => Value.CompareTo(other.Value); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=IEquatable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=IEquatable.verified.txt deleted file mode 100644 index b4c2d5867..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=IEquatable.verified.txt +++ /dev/null @@ -1,36 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IEquatable - { - public MassTransit.NewId Value { get; } - - public MyTestId(MassTransit.NewId value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(MassTransit.NewId.Next()); - public static readonly MyTestId Empty = new MyTestId(MassTransit.NewId.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=None.verified.txt deleted file mode 100644 index 7e4892f41..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=None_i=None.verified.txt +++ /dev/null @@ -1,36 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public MassTransit.NewId Value { get; } - - public MyTestId(MassTransit.NewId value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(MassTransit.NewId.Next()); - public static readonly MyTestId Empty = new MyTestId(MassTransit.NewId.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=SystemTextJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=SystemTextJson_i=None.verified.txt deleted file mode 100644 index 3de0600ab..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=MassTransitNewId_c=SystemTextJson_i=None.verified.txt +++ /dev/null @@ -1,50 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - readonly partial struct MyTestId - { - public MassTransit.NewId Value { get; } - - public MyTestId(MassTransit.NewId value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(MassTransit.NewId.Next()); - public static readonly MyTestId Empty = new MyTestId(MassTransit.NewId.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(MassTransit.NewId.FromGuid(reader.GetGuid())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value.ToGuid()); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=DapperTypeHandler_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=DapperTypeHandler_i=None.verified.txt deleted file mode 100644 index c96f1e168..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=DapperTypeHandler_i=None.verified.txt +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - readonly partial struct MyTestId - { - public string? Value { get; } - - public MyTestId(string? value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - null => new MyTestId(null), - System.DBNull => new MyTestId(null), - string stringValue => new MyTestId(stringValue), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=EfCoreValueConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=EfCoreValueConverter_i=None.verified.txt deleted file mode 100644 index e1a174104..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=EfCoreValueConverter_i=None.verified.txt +++ /dev/null @@ -1,55 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - readonly partial struct MyTestId - { - public string? Value { get; } - - public MyTestId(string? value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) - : base( - id => id.Value!, - value => new MyTestId(value), - mappingHints - ) { } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=NewtonsoftJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=NewtonsoftJson_i=None.verified.txt deleted file mode 100644 index 9660c1fc0..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=NewtonsoftJson_i=None.verified.txt +++ /dev/null @@ -1,71 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - readonly partial struct MyTestId - { - public string? Value { get; } - - public MyTestId(string? value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object? value, Newtonsoft.Json.JsonSerializer serializer) - { - if (value is null) - { - serializer.Serialize(writer, null); - } - else - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - return new MyTestId(serializer.Deserialize(reader)); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=IComparable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=IComparable.verified.txt deleted file mode 100644 index d779d1af4..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=IComparable.verified.txt +++ /dev/null @@ -1,54 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - readonly partial struct MyTestId : System.IComparable - { - public string? Value { get; } - - public MyTestId(string? value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => 0, - (null, _) => -1, - (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), - }; - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=IEquatable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=IEquatable.verified.txt deleted file mode 100644 index bb2e2c7d2..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=IEquatable.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - readonly partial struct MyTestId : System.IEquatable - { - public string? Value { get; } - - public MyTestId(string? value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=None.verified.txt deleted file mode 100644 index fe1e43665..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=None_i=None.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - readonly partial struct MyTestId - { - public string? Value { get; } - - public MyTestId(string? value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=SystemTextJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=SystemTextJson_i=None.verified.txt deleted file mode 100644 index c049fb7f5..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=SystemTextJson_i=None.verified.txt +++ /dev/null @@ -1,65 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - readonly partial struct MyTestId - { - public string? Value { get; } - - public MyTestId(string? value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(reader.GetString()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - if (value.Value is null) - { - writer.WriteNullValue(); - } - else - { - writer.WriteStringValue(value.Value); - } - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=TypeConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=TypeConverter_i=None.verified.txt deleted file mode 100644 index 50b3c0585..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=NullableString_c=TypeConverter_i=None.verified.txt +++ /dev/null @@ -1,87 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId - { - public string? Value { get; } - - public MyTestId(string? value) - { - Value = value; - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) - { - if (value is null) - { - return new MyTestId(null); - } - - var stringValue = value as string; - if (stringValue is not null) - { - return new MyTestId(stringValue); - } - - return base.ConvertFrom(context, culture, value); - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Type? sourceType) - { - return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(string)) - { - return idValue.Value; - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=DapperTypeHandler_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=DapperTypeHandler_i=None.verified.txt deleted file mode 100644 index 749dd1dbd..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=DapperTypeHandler_i=None.verified.txt +++ /dev/null @@ -1,61 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public string Value { get; } - - public MyTestId(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, MyTestId value) - { - parameter.Value = value.Value; - } - - public override MyTestId Parse(object value) - { - return value switch - { - string stringValue => new MyTestId(stringValue), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyTestId"), - }; - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=EfCoreValueConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=EfCoreValueConverter_i=None.verified.txt deleted file mode 100644 index 05700f78d..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=EfCoreValueConverter_i=None.verified.txt +++ /dev/null @@ -1,55 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public string Value { get; } - - public MyTestId(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new MyTestId(value), - mappingHints - ) { } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=NewtonsoftJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=NewtonsoftJson_i=None.verified.txt deleted file mode 100644 index d7596bf2b..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=NewtonsoftJson_i=None.verified.txt +++ /dev/null @@ -1,71 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [Newtonsoft.Json.JsonConverter(typeof(MyTestIdNewtonsoftJsonConverter))] - readonly partial struct MyTestId - { - public string Value { get; } - - public MyTestId(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyTestId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyTestId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - if (objectType == typeof(MyTestId?)) - { - var value = serializer.Deserialize(reader); - - return value is null ? null : new MyTestId(value); - } - - return new MyTestId(serializer.Deserialize(reader)); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=IComparable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=IComparable.verified.txt deleted file mode 100644 index 4fae5139a..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=IComparable.verified.txt +++ /dev/null @@ -1,54 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IComparable - { - public string Value { get; } - - public MyTestId(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - public int CompareTo(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => 0, - (null, _) => -1, - (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), - }; - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=IEquatable.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=IEquatable.verified.txt deleted file mode 100644 index 050bcc20b..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=IEquatable.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId : System.IEquatable - { - public string Value { get; } - - public MyTestId(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=None.verified.txt deleted file mode 100644 index 0987c7d64..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=None_i=None.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - readonly partial struct MyTestId - { - public string Value { get; } - - public MyTestId(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=SystemTextJson_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=SystemTextJson_i=None.verified.txt deleted file mode 100644 index 1396ccae3..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=SystemTextJson_i=None.verified.txt +++ /dev/null @@ -1,58 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - readonly partial struct MyTestId - { - public string Value { get; } - - public MyTestId(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(reader.GetString()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=TypeConverter_i=None.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=TypeConverter_i=None.verified.txt deleted file mode 100644 index d35ac20a3..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdCorrectly_type=String_c=TypeConverter_i=None.verified.txt +++ /dev/null @@ -1,82 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.ComponentModel.TypeConverter(typeof(MyTestIdTypeConverter))] - readonly partial struct MyTestId - { - public string Value { get; } - - public MyTestId(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly MyTestId Empty = new MyTestId(string.Empty); - - public bool Equals(MyTestId other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - var stringValue = value as string; - if (stringValue is not null) - { - return new MyTestId(stringValue); - } - - return base.ConvertFrom(context, culture, value); - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyTestId idValue) - { - if (destinationType == typeof(string)) - { - return idValue.Value; - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=0.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=0.verified.txt deleted file mode 100644 index ff61cdde7..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=0.verified.txt +++ /dev/null @@ -1,56 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTestNamespace -{ - partial record InnerMost - { - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - readonly partial struct MyTestId - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=1.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=1.verified.txt deleted file mode 100644 index dacf3158c..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=1.verified.txt +++ /dev/null @@ -1,59 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTestNamespace -{ - partial class OuterLayer0 - { - partial record InnerMost - { - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - readonly partial struct MyTestId - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=2.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=2.verified.txt deleted file mode 100644 index b71458e7e..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesIdWithNestedClassCorrectly_nestedClassCount=2.verified.txt +++ /dev/null @@ -1,62 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTestNamespace -{ - partial class OuterLayer1 - { - partial class OuterLayer0 - { - partial record InnerMost - { - [System.Text.Json.Serialization.JsonConverter(typeof(MyTestIdSystemTextJsonConverter))] - readonly partial struct MyTestId - { - public System.Guid Value { get; } - - public MyTestId(System.Guid value) - { - Value = value; - } - - public static MyTestId New() => new MyTestId(System.Guid.NewGuid()); - public static readonly MyTestId Empty = new MyTestId(System.Guid.Empty); - - public bool Equals(MyTestId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyTestId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyTestId a, MyTestId b) => a.Equals(b); - public static bool operator !=(MyTestId a, MyTestId b) => !(a == b); - - class MyTestIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyTestId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyTestId(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyTestId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Core3_1.received.txt new file mode 100644 index 000000000..d0568badd --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Core3_1.received.txt @@ -0,0 +1,522 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet6_0.received.txt new file mode 100644 index 000000000..d0568badd --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet6_0.received.txt @@ -0,0 +1,522 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet7_0.received.txt new file mode 100644 index 000000000..d0568badd --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet7_0.received.txt @@ -0,0 +1,522 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Net4_8.received.txt new file mode 100644 index 000000000..d0568badd --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Net4_8.received.txt @@ -0,0 +1,522 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index c23dd3c69..8ab8ff518 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -170,6 +170,143 @@ namespace StronglyTypedIds } } #endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif //------------------------------------------------------------------------------ // // This code was generated by the StronglyTypedId source generator @@ -182,8 +319,15 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented #nullable enable - [global::System.ComponentModel.TypeConverter(typeof(TypeConverter))] - readonly partial struct MyId : global::System.IComparable, global::System.IEquatable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_0_OR_GREATER + ,global::System.IParsable, global::System.ISpanParsable +#endif +#endif { public global::System.Guid Value { get; } @@ -195,8 +339,9 @@ namespace StronglyTypedIds public static MyId New() => new MyId(global::System.Guid.NewGuid()); public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -205,19 +350,21 @@ namespace StronglyTypedIds public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { @@ -227,12 +374,12 @@ namespace StronglyTypedIds }; } - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value, global::System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { @@ -250,4 +397,125 @@ namespace StronglyTypedIds return base.ConvertTo(context, culture, value, destinationType); } } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=null.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt similarity index 68% rename from test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=null.verified.txt rename to test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt index af074ad91..986563f37 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=null.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt @@ -7,7 +7,7 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { @@ -22,6 +22,7 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// If not set, uses , which defaults to /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -32,6 +33,34 @@ namespace StronglyTypedIds Implementations = implementations; } + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + /// /// The to use to store the strongly-typed ID value /// @@ -46,6 +75,16 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -56,7 +95,8 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] @@ -71,6 +111,7 @@ namespace StronglyTypedIds /// Defaults to and /// Interfaces and patterns the strongly typed id should implement /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdDefaultsAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -81,6 +122,27 @@ namespace StronglyTypedIds Implementations = implementations; } + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + /// /// The default to use to store the strongly-typed ID values. /// @@ -95,6 +157,16 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -216,6 +288,25 @@ namespace StronglyTypedIds } } #endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif //------------------------------------------------------------------------------ // // This code was generated by the StronglyTypedId source generator @@ -227,21 +318,23 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented -namespace MyTests.TestNameSpace +#nullable enable +namespace SomeNamespace { - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable + readonly partial struct MyId : INTERFACES { - public System.Guid Value { get; } + public MassTransit.NewId Value { get; } - public MyId(System.Guid value) + public MyId(MassTransit.NewId value) { Value = value; } - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); + public static MyId New() => new MyId(MassTransit.NewId.Next()); + public static readonly MyId Empty = new MyId(MassTransit.NewId.Empty); public bool Equals(MyId other) => this.Value.Equals(other.Value); public override bool Equals(object obj) @@ -255,42 +348,51 @@ namespace MyTests.TestNameSpace public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); class MyIdTypeConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || + sourceType == typeof(string) || base.CanConvertFrom + (context, sourceType); } public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { return value switch { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), + MassTransit.NewId newIdValue => new MyId(newIdValue), + System.Guid guidValue => new MyId(MassTransit.NewId.FromGuid(guidValue)), + string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(MassTransit.NewId.FromGuid(result)), _ => base.ConvertFrom(context, culture, value), }; } public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(MassTransit.NewId)) { return idValue.Value; } + if (destinationType == typeof(System.Guid)) + { + return idValue.Value.ToGuid(); + } + if (destinationType == typeof(string)) { - return idValue.Value.ToString(); + return idValue.Value.ToGuid().ToString(); } } @@ -298,24 +400,16 @@ namespace MyTests.TestNameSpace } } - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter + class MyIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter { - public override bool CanConvert(System.Type objectType) + public override MyId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { - return objectType == typeof(MyId); + return new MyId(MassTransit.NewId.FromGuid(reader.GetGuid())); } - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) + public override void Write(System.Text.Json.Utf8JsonWriter writer, MyId value, System.Text.Json.JsonSerializerOptions options) { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; + writer.WriteStringValue(value.Value.ToGuid()); } } - } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Core3_1.received.txt new file mode 100644 index 000000000..58ec20237 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Core3_1.received.txt @@ -0,0 +1,532 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass where T: new() + { + internal partial record InnerClass + { + public partial struct InnerStruct + { + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt new file mode 100644 index 000000000..58ec20237 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt @@ -0,0 +1,532 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass where T: new() + { + internal partial record InnerClass + { + public partial struct InnerStruct + { + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt new file mode 100644 index 000000000..58ec20237 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt @@ -0,0 +1,532 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass where T: new() + { + internal partial record InnerClass + { + public partial struct InnerStruct + { + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Net4_8.received.txt new file mode 100644 index 000000000..58ec20237 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Net4_8.received.txt @@ -0,0 +1,532 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass where T: new() + { + internal partial record InnerClass + { + public partial struct InnerStruct + { + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt new file mode 100644 index 000000000..72641679d --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -0,0 +1,531 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass where T: new() + { + internal partial record InnerClass + { + public partial struct InnerStruct + { + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_0_OR_GREATER + ,global::System.IParsable, global::System.ISpanParsable +#endif +#endif + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Core3_1.received.txt new file mode 100644 index 000000000..d7ab88402 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Core3_1.received.txt @@ -0,0 +1,525 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet6_0.received.txt new file mode 100644 index 000000000..d7ab88402 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet6_0.received.txt @@ -0,0 +1,525 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet7_0.received.txt new file mode 100644 index 000000000..d7ab88402 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet7_0.received.txt @@ -0,0 +1,525 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Net4_8.received.txt new file mode 100644 index 000000000..d7ab88402 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Net4_8.received.txt @@ -0,0 +1,525 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index 416efd070..d4e31ce30 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -170,6 +170,143 @@ namespace StronglyTypedIds } } #endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif //------------------------------------------------------------------------------ // // This code was generated by the StronglyTypedId source generator @@ -184,8 +321,15 @@ namespace StronglyTypedIds #nullable enable namespace SomeNamespace { - [global::System.ComponentModel.TypeConverter(typeof(TypeConverter))] - readonly partial struct MyId : global::System.IComparable, global::System.IEquatable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_0_OR_GREATER + ,global::System.IParsable, global::System.ISpanParsable +#endif +#endif { public global::System.Guid Value { get; } @@ -197,8 +341,9 @@ namespace SomeNamespace public static MyId New() => new MyId(global::System.Guid.NewGuid()); public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -207,19 +352,21 @@ namespace SomeNamespace public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { @@ -229,12 +376,12 @@ namespace SomeNamespace }; } - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value, global::System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { @@ -252,5 +399,126 @@ namespace SomeNamespace return base.ConvertTo(context, culture, value, destinationType); } } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Core3_1.received.txt new file mode 100644 index 000000000..d7ab88402 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Core3_1.received.txt @@ -0,0 +1,525 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet6_0.received.txt new file mode 100644 index 000000000..d7ab88402 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet6_0.received.txt @@ -0,0 +1,525 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt index 8e602474f..d7ab88402 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt @@ -322,13 +322,15 @@ namespace StronglyTypedIds namespace SomeNamespace { [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_OR_GREATER - global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public global::System.Guid Value { get; } @@ -340,7 +342,6 @@ namespace SomeNamespace public static MyId New() => new MyId(global::System.Guid.NewGuid()); public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - /// public bool Equals(MyId other) => this.Value.Equals(other.Value); public override bool Equals(object? obj) @@ -376,7 +377,7 @@ namespace SomeNamespace }; } - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type? sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Net4_8.received.txt new file mode 100644 index 000000000..d7ab88402 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Net4_8.received.txt @@ -0,0 +1,525 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index 416efd070..d4e31ce30 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -170,6 +170,143 @@ namespace StronglyTypedIds } } #endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif //------------------------------------------------------------------------------ // // This code was generated by the StronglyTypedId source generator @@ -184,8 +321,15 @@ namespace StronglyTypedIds #nullable enable namespace SomeNamespace { - [global::System.ComponentModel.TypeConverter(typeof(TypeConverter))] - readonly partial struct MyId : global::System.IComparable, global::System.IEquatable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_0_OR_GREATER + ,global::System.IParsable, global::System.ISpanParsable +#endif +#endif { public global::System.Guid Value { get; } @@ -197,8 +341,9 @@ namespace SomeNamespace public static MyId New() => new MyId(global::System.Guid.NewGuid()); public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -207,19 +352,21 @@ namespace SomeNamespace public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { @@ -229,12 +376,12 @@ namespace SomeNamespace }; } - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(global::System.ComponentModel.ITypeDescriptorContext context, global::System.Globalization.CultureInfo culture, object value, global::System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { @@ -252,5 +399,126 @@ namespace SomeNamespace return base.ConvertTo(context, culture, value, destinationType); } } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=NewtonsoftJson, SystemTextJson.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=NewtonsoftJson, SystemTextJson.verified.txt deleted file mode 100644 index 1be7dd3cb..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=NewtonsoftJson, SystemTextJson.verified.txt +++ /dev/null @@ -1,293 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTests.TestNameSpace -{ - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] - [System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public MyId(System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); - - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } - - class MyIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyId(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=NewtonsoftJson.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=NewtonsoftJson.verified.txt deleted file mode 100644 index a7e3384bc..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=NewtonsoftJson.verified.txt +++ /dev/null @@ -1,279 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTests.TestNameSpace -{ - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public MyId(System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); - - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=SystemTextJson.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=SystemTextJson.verified.txt deleted file mode 100644 index e8ca99b42..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=SystemTextJson.verified.txt +++ /dev/null @@ -1,272 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTests.TestNameSpace -{ - [System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public MyId(System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); - - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyId(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=TypeConverter.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=TypeConverter.verified.txt deleted file mode 100644 index 62ccb4765..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=TypeConverter.verified.txt +++ /dev/null @@ -1,300 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTests.TestNameSpace -{ - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public MyId(System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); - - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=NewtonsoftJson, SystemTextJson.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=NewtonsoftJson, SystemTextJson.verified.txt deleted file mode 100644 index 1be7dd3cb..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=NewtonsoftJson, SystemTextJson.verified.txt +++ /dev/null @@ -1,293 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTests.TestNameSpace -{ - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] - [System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public MyId(System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); - - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } - - class MyIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyId(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=NewtonsoftJson.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=NewtonsoftJson.verified.txt deleted file mode 100644 index a7e3384bc..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=NewtonsoftJson.verified.txt +++ /dev/null @@ -1,279 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTests.TestNameSpace -{ - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public MyId(System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); - - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(MyId); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=SystemTextJson.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=SystemTextJson.verified.txt deleted file mode 100644 index e8ca99b42..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=SystemTextJson.verified.txt +++ /dev/null @@ -1,272 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTests.TestNameSpace -{ - [System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public MyId(System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); - - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override MyId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new MyId(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyId value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=TypeConverter.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=TypeConverter.verified.txt deleted file mode 100644 index 62ccb4765..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithPositionalParameters_backingType=Guid_converter=TypeConverter.verified.txt +++ /dev/null @@ -1,300 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -namespace MyTests.TestNameSpace -{ - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable - { - public System.Guid Value { get; } - - public MyId(System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); - - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Core3_1.received.txt new file mode 100644 index 000000000..6e46018a3 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Core3_1.received.txt @@ -0,0 +1,742 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace MyContracts.V1 +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} + +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace MyContracts.V2 +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet6_0.received.txt new file mode 100644 index 000000000..6e46018a3 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet6_0.received.txt @@ -0,0 +1,742 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace MyContracts.V1 +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} + +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace MyContracts.V2 +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet7_0.received.txt new file mode 100644 index 000000000..6e46018a3 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet7_0.received.txt @@ -0,0 +1,742 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace MyContracts.V1 +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} + +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace MyContracts.V2 +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Net4_8.received.txt new file mode 100644 index 000000000..6e46018a3 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Net4_8.received.txt @@ -0,0 +1,742 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace MyContracts.V1 +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} + +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace MyContracts.V2 +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 4b42d88ad..6e46018a3 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -7,15 +7,37 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + /// /// Make the struct a strongly typed ID. /// /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// Templates must be added to the project using the format NAME.typedid, /// where NAME is the name of the template passed in . /// public StronglyTypedIdAttribute(string templateName) @@ -24,17 +46,45 @@ namespace StronglyTypedIds } /// - /// Make the struct a strongly typed ID, using the default settings + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template /// public StronglyTypedIdAttribute() { - TemplateName = null; } /// - /// The to use to store the strongly-typed ID value. + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. /// public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -45,20 +95,47 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdDefaultsAttribute : Attribute { /// - /// The to use to store the strongly-typed ID value + /// Set the default values used for strongly typed ids /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + /// - /// Set the default values used for strongly typed ids + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs /// /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// Templates must be added to the project using the format NAME.typedid, /// where NAME is the name of the template passed in . /// public StronglyTypedIdDefaultsAttribute(string templateName) @@ -67,9 +144,166 @@ namespace StronglyTypedIds } /// - /// The to use to store the strongly-typed ID value + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface /// - public string TemplateName { get; } + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, } } #endif @@ -84,23 +318,33 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable namespace MyContracts.V1 { - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { - public System.Guid Value { get; } + public global::System.Guid Value { get; } - public MyId(System.Guid value) + public MyId(global::System.Guid value) { Value = value; } - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -109,38 +353,40 @@ namespace MyContracts.V1 public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value; } @@ -154,6 +400,127 @@ namespace MyContracts.V1 return base.ConvertTo(context, culture, value, destinationType); } } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif } } @@ -168,23 +535,33 @@ namespace MyContracts.V1 #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable namespace MyContracts.V2 { - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { - public System.Guid Value { get; } + public global::System.Guid Value { get; } - public MyId(System.Guid value) + public MyId(global::System.Guid value) { Value = value; } - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -193,38 +570,40 @@ namespace MyContracts.V2 public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value; } @@ -238,5 +617,126 @@ namespace MyContracts.V2 return base.ConvertTo(context, culture, value, destinationType); } } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Core3_1.received.txt new file mode 100644 index 000000000..6197b7590 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Core3_1.received.txt @@ -0,0 +1,528 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass + { + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet6_0.received.txt new file mode 100644 index 000000000..6197b7590 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet6_0.received.txt @@ -0,0 +1,528 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass + { + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet7_0.received.txt new file mode 100644 index 000000000..6197b7590 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet7_0.received.txt @@ -0,0 +1,528 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass + { + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Net4_8.received.txt new file mode 100644 index 000000000..6197b7590 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Net4_8.received.txt @@ -0,0 +1,528 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass + { + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index 2d2fb86fc..fc77f9d25 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -7,15 +7,37 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + /// /// Make the struct a strongly typed ID. /// /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// Templates must be added to the project using the format NAME.typedid, /// where NAME is the name of the template passed in . /// public StronglyTypedIdAttribute(string templateName) @@ -24,17 +46,45 @@ namespace StronglyTypedIds } /// - /// Make the struct a strongly typed ID, using the default settings + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template /// public StronglyTypedIdAttribute() { - TemplateName = null; } /// - /// The to use to store the strongly-typed ID value. + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. /// public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -45,20 +95,47 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdDefaultsAttribute : Attribute { /// - /// The to use to store the strongly-typed ID value + /// Set the default values used for strongly typed ids /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + /// - /// Set the default values used for strongly typed ids + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs /// /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// Templates must be added to the project using the format NAME.typedid, /// where NAME is the name of the template passed in . /// public StronglyTypedIdDefaultsAttribute(string templateName) @@ -67,9 +144,166 @@ namespace StronglyTypedIds } /// - /// The to use to store the strongly-typed ID value + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. /// - public string TemplateName { get; } + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, } } #endif @@ -84,25 +318,34 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable namespace SomeNamespace { - partial class ParentClass + public partial class ParentClass { - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_0_OR_GREATER + ,global::System.IParsable, global::System.ISpanParsable +#endif +#endif { - public System.Guid Value { get; } + public global::System.Guid Value { get; } - public MyId(System.Guid value) + public MyId(global::System.Guid value) { Value = value; } - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -111,38 +354,40 @@ namespace SomeNamespace public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value; } @@ -156,6 +401,127 @@ namespace SomeNamespace return base.ConvertTo(context, culture, value, destinationType); } } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif } } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt new file mode 100644 index 000000000..cc5be7be6 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -0,0 +1,520 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public int Value { get; } + + public MyId(int value) + { + Value = value; + } + + public static readonly MyId Empty = new MyId(0); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + int intValue => new MyId(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt32()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static MyId Parse(string input) + => new(int.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(int.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (int.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(int.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(int.Parse(input, provider)); +#else + => new(int.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (int.TryParse(input, provider, out var guid)) +#else + if (int.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Core3_1.received.txt new file mode 100644 index 000000000..7609f784c --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Core3_1.received.txt @@ -0,0 +1,534 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass + { + internal partial record InnerClass + { + public readonly partial record InnerStruct + { + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt new file mode 100644 index 000000000..7609f784c --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt @@ -0,0 +1,534 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass + { + internal partial record InnerClass + { + public readonly partial record InnerStruct + { + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt new file mode 100644 index 000000000..7609f784c --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt @@ -0,0 +1,534 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass + { + internal partial record InnerClass + { + public readonly partial record InnerStruct + { + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Net4_8.received.txt new file mode 100644 index 000000000..7609f784c --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Net4_8.received.txt @@ -0,0 +1,534 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable +namespace SomeNamespace +{ + public partial class ParentClass + { + internal partial record InnerClass + { + public readonly partial record InnerStruct + { + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } + } + } + } +} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index 37acd1a1a..90f845d71 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -7,15 +7,37 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + /// /// Make the struct a strongly typed ID. /// /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// Templates must be added to the project using the format NAME.typedid, /// where NAME is the name of the template passed in . /// public StronglyTypedIdAttribute(string templateName) @@ -24,17 +46,45 @@ namespace StronglyTypedIds } /// - /// Make the struct a strongly typed ID, using the default settings + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template /// public StronglyTypedIdAttribute() { - TemplateName = null; } /// - /// The to use to store the strongly-typed ID value. + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. /// public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -45,20 +95,47 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdDefaultsAttribute : Attribute { /// - /// The to use to store the strongly-typed ID value + /// Set the default values used for strongly typed ids /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + /// - /// Set the default values used for strongly typed ids + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs /// /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// Templates must be added to the project using the format NAME.typedid, /// where NAME is the name of the template passed in . /// public StronglyTypedIdDefaultsAttribute(string templateName) @@ -67,9 +144,166 @@ namespace StronglyTypedIds } /// - /// The to use to store the strongly-typed ID value + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. /// - public string TemplateName { get; } + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, } } #endif @@ -84,29 +318,38 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented +#nullable enable namespace SomeNamespace { - partial class ParentClass where T: new() + public partial class ParentClass { - partial record InnerClass + internal partial record InnerClass { - partial struct InnerStruct + public readonly partial record InnerStruct { - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_0_OR_GREATER + ,global::System.IParsable, global::System.ISpanParsable +#endif +#endif { - public System.Guid Value { get; } + public global::System.Guid Value { get; } - public MyId(System.Guid value) + public MyId(global::System.Guid value) { Value = value; } - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -115,38 +358,40 @@ namespace SomeNamespace public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value; } @@ -160,6 +405,127 @@ namespace SomeNamespace return base.ConvertTo(context, culture, value, destinationType); } } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif } } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.DotNet7_0.received.txt new file mode 100644 index 000000000..d6f15d917 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.DotNet7_0.received.txt @@ -0,0 +1,521 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int32, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_0_OR_GREATER + ,global::System.IParsable, global::System.ISpanParsable +#endif +#endif + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt index e7bc0d334..5f282702b 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt @@ -1,154 +1 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default settings - /// - public StronglyTypedIdAttribute() - { - TemplateName = null; - } - - /// - /// The to use to store the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// The to use to store the strongly-typed ID value - /// - /// - /// Set the default values used for strongly typed ids - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The to use to store the strongly-typed ID value - /// - public string TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable - { - public int Value { get; } - - public MyId(int value) - { - Value = value; - } - - public static readonly MyId Empty = new MyId(0); - - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - int intValue => new MyId(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(int)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } + \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=null.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt similarity index 68% rename from test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=null.verified.txt rename to test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt index af074ad91..d568f0d58 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdWithNamedParameters_backingType=Guid_converter=null.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt @@ -7,7 +7,7 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { @@ -22,6 +22,7 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// If not set, uses , which defaults to /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -32,6 +33,34 @@ namespace StronglyTypedIds Implementations = implementations; } + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + /// /// The to use to store the strongly-typed ID value /// @@ -46,6 +75,16 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -56,7 +95,8 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] @@ -71,6 +111,7 @@ namespace StronglyTypedIds /// Defaults to and /// Interfaces and patterns the strongly typed id should implement /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] public StronglyTypedIdDefaultsAttribute( StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, @@ -81,6 +122,27 @@ namespace StronglyTypedIds Implementations = implementations; } + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + /// /// The default to use to store the strongly-typed ID values. /// @@ -95,6 +157,16 @@ namespace StronglyTypedIds /// Interfaces and patterns the strongly typed id should implement /// public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -216,6 +288,25 @@ namespace StronglyTypedIds } } #endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif //------------------------------------------------------------------------------ // // This code was generated by the StronglyTypedId source generator @@ -227,21 +318,21 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented -namespace MyTests.TestNameSpace -{ - [Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable + readonly partial struct MyId : INTERFACES { - public System.Guid Value { get; } + public MassTransit.NewId Value { get; } - public MyId(System.Guid value) + public MyId(MassTransit.NewId value) { Value = value; } - public static MyId New() => new MyId(System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(System.Guid.Empty); + public static MyId New() => new MyId(MassTransit.NewId.Next()); + public static readonly MyId Empty = new MyId(MassTransit.NewId.Empty); public bool Equals(MyId other) => this.Value.Equals(other.Value); public override bool Equals(object obj) @@ -255,42 +346,51 @@ namespace MyTests.TestNameSpace public override string ToString() => Value.ToString(); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public int CompareTo(MyId other) => Value.CompareTo(other.Value); class MyIdTypeConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || + sourceType == typeof(string) || base.CanConvertFrom + (context, sourceType); } public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { return value switch { - System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(result), + MassTransit.NewId newIdValue => new MyId(newIdValue), + System.Guid guidValue => new MyId(MassTransit.NewId.FromGuid(guidValue)), + string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(MassTransit.NewId.FromGuid(result)), _ => base.ConvertFrom(context, culture, value), }; } public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(MassTransit.NewId)) { return idValue.Value; } + if (destinationType == typeof(System.Guid)) + { + return idValue.Value.ToGuid(); + } + if (destinationType == typeof(string)) { - return idValue.Value.ToString(); + return idValue.Value.ToGuid().ToString(); } } @@ -298,24 +398,15 @@ namespace MyTests.TestNameSpace } } - class MyIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter + class MyIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter { - public override bool CanConvert(System.Type objectType) + public override MyId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { - return objectType == typeof(MyId); + return new MyId(MassTransit.NewId.FromGuid(reader.GetGuid())); } - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) + public override void Write(System.Text.Json.Utf8JsonWriter writer, MyId value, System.Text.Json.JsonSerializerOptions options) { - var id = (MyId)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new MyId(guid.Value) : null; + writer.WriteStringValue(value.Value.ToGuid()); } } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Core3_1.received.txt new file mode 100644 index 000000000..4da683f8a --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Core3_1.received.txt @@ -0,0 +1,517 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public int Value { get; } + + public MyId(int value) + { + Value = value; + } + + public static readonly MyId Empty = new MyId(0); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + int intValue => new MyId(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt32()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static MyId Parse(string input) + => new(int.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(int.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (int.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(int.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(int.Parse(input, provider)); +#else + => new(int.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (int.TryParse(input, provider, out var guid)) +#else + if (int.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet6_0.received.txt new file mode 100644 index 000000000..4da683f8a --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet6_0.received.txt @@ -0,0 +1,517 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public int Value { get; } + + public MyId(int value) + { + Value = value; + } + + public static readonly MyId Empty = new MyId(0); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + int intValue => new MyId(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt32()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static MyId Parse(string input) + => new(int.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(int.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (int.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(int.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(int.Parse(input, provider)); +#else + => new(int.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (int.TryParse(input, provider, out var guid)) +#else + if (int.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet7_0.received.txt new file mode 100644 index 000000000..4da683f8a --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet7_0.received.txt @@ -0,0 +1,517 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public int Value { get; } + + public MyId(int value) + { + Value = value; + } + + public static readonly MyId Empty = new MyId(0); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + int intValue => new MyId(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt32()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static MyId Parse(string input) + => new(int.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(int.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (int.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(int.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(int.Parse(input, provider)); +#else + => new(int.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (int.TryParse(input, provider, out var guid)) +#else + if (int.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Net4_8.received.txt new file mode 100644 index 000000000..4da683f8a --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Net4_8.received.txt @@ -0,0 +1,517 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public int Value { get; } + + public MyId(int value) + { + Value = value; + } + + public static readonly MyId Empty = new MyId(0); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + int intValue => new MyId(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt32()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static MyId Parse(string input) + => new(int.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(int.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (int.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(int.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(int.Parse(input, provider)); +#else + => new(int.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (int.TryParse(input, provider, out var guid)) +#else + if (int.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt new file mode 100644 index 000000000..47135128d --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -0,0 +1,516 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable +#endif +#endif + { + public int Value { get; } + + public MyId(int value) + { + Value = value; + } + + public static readonly MyId Empty = new MyId(0); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + int intValue => new MyId(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt32()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static MyId Parse(string input) + => new(int.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(int.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (int.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(int.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(int.Parse(input, provider)); +#else + => new(int.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (int.TryParse(input, provider, out var guid)) +#else + if (int.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Core3_1.received.txt new file mode 100644 index 000000000..d0568badd --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Core3_1.received.txt @@ -0,0 +1,522 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet6_0.received.txt new file mode 100644 index 000000000..d0568badd --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet6_0.received.txt @@ -0,0 +1,522 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet7_0.received.txt new file mode 100644 index 000000000..d0568badd --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet7_0.received.txt @@ -0,0 +1,522 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Net4_8.received.txt new file mode 100644 index 000000000..d0568badd --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Net4_8.received.txt @@ -0,0 +1,522 @@ +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : Attribute + { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + { + /// + /// Set the default values used for strongly typed ids + /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt index e7bc0d334..8ab8ff518 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt @@ -7,15 +7,37 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : Attribute { + /// + /// Make the struct a strongly typed ID + /// + /// The to use to store the strongly-typed ID value. + /// If not set, uses , which defaults to + /// Converters to create for serializing/deserializing the strongly-typed ID value. + /// If not set, uses , which defaults to + /// and + /// Interfaces and patterns the strongly typed id should implement + /// If not set, uses , which defaults to + /// and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + /// /// Make the struct a strongly typed ID. /// /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// Templates must be added to the project using the format NAME.typedid, /// where NAME is the name of the template passed in . /// public StronglyTypedIdAttribute(string templateName) @@ -24,17 +46,45 @@ namespace StronglyTypedIds } /// - /// Make the struct a strongly typed ID, using the default settings + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID, using the default template /// public StronglyTypedIdAttribute() { - TemplateName = null; } /// - /// The to use to store the strongly-typed ID value. + /// The to use to store the strongly-typed ID value + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// JSON library used to serialize/deserialize strongly-typed ID value + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The template to use to generate the strongly-typed ID value. /// public string? TemplateName { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } } } #endif @@ -45,20 +95,47 @@ using System; namespace StronglyTypedIds { /// - /// Used to control the default Place on partial structs to make the type a strongly-typed ID + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdDefaultsAttribute : Attribute { /// - /// The to use to store the strongly-typed ID value + /// Set the default values used for strongly typed ids /// + /// The to use to store the strongly-typed ID value. + /// Defaults to + /// JSON library used to serialize/deserialize strongly-typed ID value. + /// Defaults to and + /// Interfaces and patterns the strongly typed id should implement + /// Defaults to and + [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] + public StronglyTypedIdDefaultsAttribute( + StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, + StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, + StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + { + BackingType = backingType; + Converters = converters; + Implementations = implementations; + } + /// - /// Set the default values used for strongly typed ids + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs /// /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format StronglyTypedId_NAME.txt, + /// Templates must be added to the project using the format NAME.typedid, /// where NAME is the name of the template passed in . /// public StronglyTypedIdDefaultsAttribute(string templateName) @@ -67,9 +144,166 @@ namespace StronglyTypedIds } /// - /// The to use to store the strongly-typed ID value + /// The default to use to store the strongly-typed ID values. + /// + public StronglyTypedIdBackingType BackingType { get; } + + /// + /// The default converters to create for serializing/deserializing strongly-typed ID values. + /// + public StronglyTypedIdConverter Converters { get; } + + /// + /// Interfaces and patterns the strongly typed id should implement + /// + public StronglyTypedIdImplementations Implementations { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. /// - public string TemplateName { get; } + public string? TemplateName { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public Template? Template { get; } + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The to use to store the value of a strongly-typed ID + /// + internal enum StronglyTypedIdBackingType + { + /// + /// Use the default backing type (either the globally configured default, or Guid) + /// + Default = 0, + + Guid = 1, + Int = 2, + String = 3, + Long = 4, + NullableString = 5, + MassTransitNewId = 6, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Converters used to to serialize/deserialize strongly-typed ID values + /// + [Flags] + internal enum StronglyTypedIdConverter + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't create any converters for the strongly typed ID + /// + None = 0, + + /// + /// Use the default converters for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + /// + /// Creates a for converting from the strongly typed ID to and from a string + /// + TypeConverter = 2, + + /// + /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value + /// + NewtonsoftJson = 4, + + /// + /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value + /// + SystemTextJson = 8, + + /// + /// Creates an EF Core Value Converter for extracting the primitive value + /// + EfCoreValueConverter = 16, + + /// + /// Creates a Dapper TypeHandler for converting to and from the type + /// + DapperTypeHandler = 32, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// Interfaces and patterns the strongly typed id should implement + /// + [Flags] + internal enum StronglyTypedIdImplementations + { + // Used with HasFlag, so needs to be 1, 2, 4 etc + + /// + /// Don't implement any additional members for the strongly typed ID + /// + None = 0, + + /// + /// Use the default implementations for the strongly typed Id. + /// This will be the value provided in the , which falls back to + /// and + /// + Default = 1, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IEquatable = 2, + + // ReSharper disable once InconsistentNaming + /// + /// Implement the interface + /// + IComparable = 4, + } +} +#endif +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, } } #endif @@ -84,20 +318,30 @@ namespace StronglyTypedIds #pragma warning disable 1591 // publicly visible type or member must be documented - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : System.IComparable, System.IEquatable +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable +#if NET6_0_OR_GREATER + ,global::System.ISpanFormattable +#if NET7_0_OR_GREATER + ,global::System.IParsable, global::System.ISpanParsable +#endif +#endif { - public int Value { get; } + public global::System.Guid Value { get; } - public MyId(int value) + public MyId(global::System.Guid value) { Value = value; } - public static readonly MyId Empty = new MyId(0); + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -106,38 +350,40 @@ namespace StronglyTypedIds public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { - int intValue => new MyId(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(int)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value; } @@ -151,4 +397,125 @@ namespace StronglyTypedIds return base.ConvertTo(context, culture, value, destinationType); } } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString()!)); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif } diff --git a/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs b/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs index 277b2dc32..8f04986b6 100644 --- a/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs +++ b/test/StronglyTypedIds.Tests/SourceGenerationHelperSnapshotTests.cs @@ -21,48 +21,7 @@ // idName: idName, // idNamespace: IdNamespace, // parentClass: null, -// converters: StronglyTypedIdConverter.None, -// backingType: StronglyTypedIdBackingType.Guid, -// implementations: StronglyTypedIdImplementations.None -// )); -// } -// -// [Fact] -// public void ThrowsWhenDefaultConverterIsUsed() -// { -// Assert.Throws(() => SourceGenerationHelper.CreateId( -// idName: "MyTestId", -// idNamespace: IdNamespace, -// parentClass: null, -// converters: StronglyTypedIdConverter.Default, -// backingType: StronglyTypedIdBackingType.Guid, -// implementations: StronglyTypedIdImplementations.None -// )); -// } -// -// [Fact] -// public void ThrowsWhenDefaultBackingTypeIsUsed() -// { -// Assert.Throws(() => SourceGenerationHelper.CreateId( -// idName: "MyTestId", -// idNamespace: IdNamespace, -// parentClass: null, -// converters: StronglyTypedIdConverter.None, -// backingType: StronglyTypedIdBackingType.Default, -// implementations: StronglyTypedIdImplementations.None -// )); -// } -// -// [Fact] -// public void ThrowsWhenDefaultImplementationsIsUsed() -// { -// Assert.Throws(() => SourceGenerationHelper.CreateId( -// idName: "MyTestId", -// idNamespace: IdNamespace, -// parentClass: null, -// converters: StronglyTypedIdConverter.None, -// backingType: StronglyTypedIdBackingType.Guid, -// implementations: StronglyTypedIdImplementations.Default +// template: "N/A" // )); // } // diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs index 597716f00..7ca832f04 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs +++ b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs @@ -32,21 +32,65 @@ public partial struct MyId {}"; .UseDirectory("Snapshots"); } + [Theory] + [InlineData("")] + [InlineData("Template.Guid")] + public Task CanGenerateIdInNamespace(string template) + { + var input = $$""" + using StronglyTypedIds; + namespace SomeNamespace + { + [StronglyTypedId({{template}})] + public partial struct MyId {} + } + """; + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + + Assert.Empty(diagnostics); + + return Verifier.Verify(output) + .DisableRequireUniquePrefix() + .UseDirectory("Snapshots"); + } + [Fact] - public Task CanGenerateIdInNamespace() + public Task CanGenerateNonDefaultIdInNamespace() { - const string input = @"using StronglyTypedIds; + var input = $$""" + using StronglyTypedIds; + namespace SomeNamespace + { + [StronglyTypedId(Template.Int)] + public partial struct MyId {} + } + """; + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); -namespace SomeNamespace -{ - [StronglyTypedId()] - public partial struct MyId {} -}"; + Assert.Empty(diagnostics); + + return Verifier.Verify(output) + .DisableRequireUniquePrefix() + .UseDirectory("Snapshots"); + } + + [Fact] + public Task CanGenerateForCustomTemplate() + { + var input = """ + using StronglyTypedIds; + namespace SomeNamespace + { + [StronglyTypedId("newid")] + public partial struct MyId {} + } + """; var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); Assert.Empty(diagnostics); return Verifier.Verify(output) + .DisableRequireUniquePrefix() .UseDirectory("Snapshots"); } @@ -93,6 +137,32 @@ public Task CanGenerateVeryNestedIdInFileScopeNamespace() namespace SomeNamespace; +public partial class ParentClass +{ + internal partial record InnerClass + { + public readonly partial record struct InnerStruct + { + [StronglyTypedId] + public readonly partial struct MyId {} + } + } +}"; + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + + Assert.Empty(diagnostics); + + return Verifier.Verify(output) + .UseDirectory("Snapshots"); + } + + [Fact] + public Task CanGenerateGenericVeryNestedIdInFileScopeNamespace() + { + const string input = @"using StronglyTypedIds; + +namespace SomeNamespace; + public class ParentClass where T: new() { @@ -114,11 +184,30 @@ public partial struct MyId {} } [Fact] - public Task CanOverrideDefaultsUsingGlobalAttribute() + public Task CanOverrideDefaultsWithTemplateUsingGlobalAttribute() { const string input = """ using StronglyTypedIds; - [assembly:StronglyTypedIdDefaults("int")] + [assembly:StronglyTypedIdDefaults(Template.Int)] + + [StronglyTypedId] + public partial struct MyId {} + """; + + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + + Assert.Empty(diagnostics); + + return Verifier.Verify(output) + .UseDirectory("Snapshots"); + } + + [Fact] + public Task CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute() + { + const string input = """ + using StronglyTypedIds; + [assembly:StronglyTypedIdDefaults("newid")] [StronglyTypedId] public partial struct MyId {} diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj index 5eb727e13..6ee5e30ff 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj +++ b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj @@ -19,16 +19,7 @@ - - - Templates\guid.typedid - - - Templates\int.typedid - - - Templates\long.typedid - + @@ -42,4 +33,8 @@ + + + + diff --git a/test/StronglyTypedIds.Tests/TestHelpers.cs b/test/StronglyTypedIds.Tests/TestHelpers.cs index 4be1e841a..2300a54e6 100644 --- a/test/StronglyTypedIds.Tests/TestHelpers.cs +++ b/test/StronglyTypedIds.Tests/TestHelpers.cs @@ -48,7 +48,7 @@ private static ImmutableArray LoadEmbeddedResourcesAsAdditionalT texts.AddRange(assembly.GetManifestResourceNames() .Select(name => new TestAdditionalText( text: LoadEmbeddedResource(assembly, name), - path: $"C:\\test\\Templates\\{Path.GetExtension(Path.GetFileNameWithoutExtension(name)).Substring(1)}.txt"))); + path: $"C:\\test\\Templates\\{Path.GetExtension(Path.GetFileNameWithoutExtension(name)).Substring(1)}.typedid"))); return texts.ToImmutable(); } From a31e0f3936b760ec0e4deffd522062c3cafc9bf0 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Wed, 1 Nov 2023 22:02:49 +0000 Subject: [PATCH 04/47] Add long and .net 8 support --- src/StronglyTypedIds/EmbeddedSources.Long.cs | 201 +++++ src/StronglyTypedIds/EmbeddedSources.cs | 1 + .../Templates/long-full.typedid | 245 ++++++ src/StronglyTypedIds/Templates/long.typedid | 70 -- test/IntegrationLibraries.props | 8 +- .../DapperTypeHandlers.cs | 2 +- .../Enums.cs | 9 +- .../LongIdTests.cs | 681 ++++++++-------- .../StronglyTypedIds.IntegrationTests.csproj | 2 +- ...ltIdInGlobalNamespace.Core3_1.received.txt | 522 ------------ ...IdInGlobalNamespace.DotNet6_0.received.txt | 522 ------------ ...IdInGlobalNamespace.DotNet7_0.received.txt | 522 ------------ ...ultIdInGlobalNamespace.Net4_8.received.txt | 522 ------------ ...ateDefaultIdInGlobalNamespace.verified.txt | 9 +- ...dInFileScopeNamespace.Core3_1.received.txt | 532 ------------- ...nFileScopeNamespace.DotNet6_0.received.txt | 532 ------------- ...nFileScopeNamespace.DotNet7_0.received.txt | 532 ------------- ...IdInFileScopeNamespace.Net4_8.received.txt | 532 ------------- ...yNestedIdInFileScopeNamespace.verified.txt | 9 +- ...InFileScopedNamespace.Core3_1.received.txt | 525 ------------- ...FileScopedNamespace.DotNet6_0.received.txt | 525 ------------- ...FileScopedNamespace.DotNet7_0.received.txt | 525 ------------- ...dInFileScopedNamespace.Net4_8.received.txt | 525 ------------- ...nerateIdInFileScopedNamespace.verified.txt | 9 +- ...GenerateIdInNamespace.Core3_1.received.txt | 525 ------------- ...nerateIdInNamespace.DotNet6_0.received.txt | 525 ------------- ...nerateIdInNamespace.DotNet7_0.received.txt | 525 ------------- ...nGenerateIdInNamespace.Net4_8.received.txt | 525 ------------- ...ests.CanGenerateIdInNamespace.verified.txt | 9 +- ...ltipleIdsWithSameName.Core3_1.received.txt | 742 ------------------ ...ipleIdsWithSameName.DotNet6_0.received.txt | 742 ------------------ ...ipleIdsWithSameName.DotNet7_0.received.txt | 742 ------------------ ...ultipleIdsWithSameName.Net4_8.received.txt | 742 ------------------ ...dInFileScopeNamespace.Core3_1.received.txt | 528 ------------- ...nFileScopeNamespace.DotNet6_0.received.txt | 528 ------------- ...nFileScopeNamespace.DotNet7_0.received.txt | 528 ------------- ...IdInFileScopeNamespace.Net4_8.received.txt | 528 ------------- ...eNestedIdInFileScopeNamespace.verified.txt | 9 +- ...nerateNonDefaultIdInNamespace.verified.txt | 4 +- ...dInFileScopeNamespace.Core3_1.received.txt | 534 ------------- ...nFileScopeNamespace.DotNet6_0.received.txt | 534 ------------- ...nFileScopeNamespace.DotNet7_0.received.txt | 534 ------------- ...IdInFileScopeNamespace.Net4_8.received.txt | 534 ------------- ...yNestedIdInFileScopeNamespace.verified.txt | 9 +- ...eUsingGlobalAttribute.Core3_1.received.txt | 517 ------------ ...singGlobalAttribute.DotNet6_0.received.txt | 517 ------------ ...singGlobalAttribute.DotNet7_0.received.txt | 517 ------------ ...teUsingGlobalAttribute.Net4_8.received.txt | 517 ------------ ...hTemplateUsingGlobalAttribute.verified.txt | 13 +- ...sGeneratesWithDefault.Core3_1.received.txt | 522 ------------ ...eneratesWithDefault.DotNet6_0.received.txt | 522 ------------ ...eneratesWithDefault.DotNet7_0.received.txt | 522 ------------ ...esGeneratesWithDefault.Net4_8.received.txt | 522 ------------ ...ttributesGeneratesWithDefault.verified.txt | 9 +- 54 files changed, 832 insertions(+), 20255 deletions(-) create mode 100644 src/StronglyTypedIds/EmbeddedSources.Long.cs create mode 100644 src/StronglyTypedIds/Templates/long-full.typedid delete mode 100644 src/StronglyTypedIds/Templates/long.typedid delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Core3_1.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet6_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Net4_8.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Core3_1.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Net4_8.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Core3_1.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet6_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Net4_8.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Core3_1.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet6_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Net4_8.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Core3_1.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet6_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Net4_8.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Core3_1.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet6_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Net4_8.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Core3_1.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Net4_8.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Core3_1.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet6_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Net4_8.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Core3_1.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet6_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet7_0.received.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Net4_8.received.txt diff --git a/src/StronglyTypedIds/EmbeddedSources.Long.cs b/src/StronglyTypedIds/EmbeddedSources.Long.cs new file mode 100644 index 000000000..ab79bb335 --- /dev/null +++ b/src/StronglyTypedIds/EmbeddedSources.Long.cs @@ -0,0 +1,201 @@ +namespace StronglyTypedIds; + +internal static partial class EmbeddedSources +{ + private const string LongTemplate = """ + partial struct PLACEHOLDERID : + #if NET6_0_OR_GREATER + global::System.ISpanFormattable, + #endif + #if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, + #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public long Value { get; } + + public PLACEHOLDERID(long value) + { + Value = value; + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(0); + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + long longValue => new PLACEHOLDERID(longValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(long)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(long) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt64()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + + #if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt64()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); + #endif + } + + public static PLACEHOLDERID Parse(string input) + => new(long.Parse(input)); + + #if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(long.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (long.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } + #endif + + /// + public string ToString( + #if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + #endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + + #if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(long.Parse(input)); + #endif + + #if NET6_0_OR_GREATER + #if NET7_0_OR_GREATER + /// + #endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) + #if NET7_0_OR_GREATER + => new(long.Parse(input, provider)); + #else + => new(long.Parse(input)); + #endif + + #if NET7_0_OR_GREATER + /// + #endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { + #if NET7_0_OR_GREATER + if (long.TryParse(input, provider, out var guid)) + #else + if (long.TryParse(input, out var guid)) + #endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + #if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + #endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + #if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + #endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); + #endif + } + """; +} \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.cs b/src/StronglyTypedIds/EmbeddedSources.cs index a9f644863..77bbf922c 100644 --- a/src/StronglyTypedIds/EmbeddedSources.cs +++ b/src/StronglyTypedIds/EmbeddedSources.cs @@ -22,6 +22,7 @@ internal static string GetTemplate(Template template) { Template.Guid => GuidTemplate, Template.Int => IntTemplate, + Template.Long => LongTemplate, _ => string.Empty, }; diff --git a/src/StronglyTypedIds/Templates/long-full.typedid b/src/StronglyTypedIds/Templates/long-full.typedid new file mode 100644 index 000000000..55d094b4b --- /dev/null +++ b/src/StronglyTypedIds/Templates/long-full.typedid @@ -0,0 +1,245 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public long Value { get; } + + public PLACEHOLDERID(long value) + { + Value = value; + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(0); + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + long intValue => new PLACEHOLDERID(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(long)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(long) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetInt32()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(long.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(long.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (long.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(long.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(long.Parse(input, provider)); +#else + => new(long.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { +#if NET7_0_OR_GREATER + if (long.TryParse(input, provider, out var guid)) +#else + if (long.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + long longValue => new PLACEHOLDERID(longValue), + int intValue => new PLACEHOLDERID(intValue), + short shortValue => new PLACEHOLDERID(shortValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var result = serializer.Deserialize(reader); + return result.HasValue ? new PLACEHOLDERID(result.Value) : null; + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/long.typedid b/src/StronglyTypedIds/Templates/long.typedid deleted file mode 100644 index 299ae0361..000000000 --- a/src/StronglyTypedIds/Templates/long.typedid +++ /dev/null @@ -1,70 +0,0 @@ - [System.ComponentModel.TypeConverter(typeof(TESTIDTypeConverter))] - readonly partial struct TESTID : System.IComparable, System.IEquatable - { - public int Value { get; } - - public TESTID(int value) - { - Value = value; - } - - public static readonly TESTID Empty = new TESTID(0); - - public bool Equals(TESTID other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is TESTID other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); - public static bool operator !=(TESTID a, TESTID b) => !(a == b); - - public int CompareTo(TESTID other) => Value.CompareTo(other.Value); - - class TESTIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(long) || sourceType == typeof(int) || sourceType == typeof(short) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - long longValue => new TESTID(longValue), - int intValue => new TESTID(intValue), - short shortValue => new TESTID(shortValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new TESTID(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is TESTID idValue) - { - if (destinationType == typeof(long)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - } \ No newline at end of file diff --git a/test/IntegrationLibraries.props b/test/IntegrationLibraries.props index 33b690855..148bedfde 100644 --- a/test/IntegrationLibraries.props +++ b/test/IntegrationLibraries.props @@ -1,20 +1,22 @@ + + + + + - - - diff --git a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs index 5362a6bbe..da182a7e8 100644 --- a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs +++ b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs @@ -11,8 +11,8 @@ public static void AddHandlers() { SqlMapper.AddTypeHandler(new ConvertersGuidId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersIntId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new ConvertersLongId.DapperTypeHandler()); // SqlMapper.AddTypeHandler(new DapperStringId.DapperTypeHandler()); - // SqlMapper.AddTypeHandler(new DapperLongId.DapperTypeHandler()); // SqlMapper.AddTypeHandler(new DapperNullableStringId.DapperTypeHandler()); // SqlMapper.AddTypeHandler(new DapperNewIdId.DapperTypeHandler()); } diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index 2a273ea10..1b2522517 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -24,9 +24,12 @@ partial struct IntId { } [StronglyTypedId("int-full")] partial struct ConvertersIntId { } -// -// [StronglyTypedId(Template.Long)] -// partial struct LongId { } + +[StronglyTypedId(Template.Long)] +partial struct LongId { } + +[StronglyTypedId("long-full")] +partial struct ConvertersLongId { } [StronglyTypedId("newid")] partial struct NewIdId1 { } diff --git a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs index 7b940308b..a681f045e 100644 --- a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs @@ -1,353 +1,328 @@ -// using System; -// using System.ComponentModel; -// using System.Linq; -// using System.Threading.Tasks; -// using Dapper; -// using Microsoft.Data.Sqlite; -// using Microsoft.EntityFrameworkCore; -// using StronglyTypedIds.IntegrationTests.Types; -// using Xunit; -// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; -// -// namespace StronglyTypedIds.IntegrationTests -// { -// public class LongIdTests -// { -// [Fact] -// public void SameValuesAreEqual() -// { -// var id = 123L; -// var foo1 = new LongId(id); -// var foo2 = new LongId(id); -// -// Assert.Equal(foo1, foo2); -// } -// -// [Fact] -// public void EmptyValueIsEmpty() -// { -// Assert.Equal(0, LongId.Empty.Value); -// } -// -// -// [Fact] -// public void DifferentValuesAreUnequal() -// { -// var foo1 = new LongId(1L); -// var foo2 = new LongId(2L); -// -// Assert.NotEqual(foo1, foo2); -// } -// -// [Fact] -// public void OverloadsWorkCorrectly() -// { -// var id = 12L; -// var same1 = new LongId(id); -// var same2 = new LongId(id); -// var different = new LongId(3L); -// -// Assert.True(same1 == same2); -// Assert.False(same1 == different); -// Assert.False(same1 != same2); -// Assert.True(same1 != different); -// } -// -// [Fact] -// public void DifferentTypesAreUnequal() -// { -// var bar = GuidId2.New(); -// var foo = new LongId(23L); -// -// //Assert.NotEqual(bar, foo); // does not compile -// Assert.NotEqual((object)bar, (object)foo); -// } -// -// [Fact] -// public void CanSerializeToLong_WithNewtonsoftJsonProvider() -// { -// var foo = new NewtonsoftJsonLongId(123); -// -// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedLong = NewtonsoftJsonSerializer.SerializeObject(foo.Value); -// -// Assert.Equal(serializedFoo, serializedLong); -// } -// -// [Fact] -// public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() -// { -// var entity = new EntityWithNullableId { Id = null }; -// -// var json = NewtonsoftJsonSerializer.SerializeObject(entity); -// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); -// -// Assert.NotNull(deserialize); -// Assert.Null(deserialize.Id); -// } -// -// [Fact] -// public void CanSerializeToLong_WithSystemTextJsonProvider() -// { -// var foo = new SystemTextJsonLongId(123L); -// -// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); -// var serializedLong = SystemTextJsonSerializer.Serialize(foo.Value); -// -// Assert.Equal(serializedFoo, serializedLong); -// } -// -// [Fact] -// public void CanDeserializeFromLong_WithNewtonsoftJsonProvider() -// { -// var value = 123L; -// var foo = new NewtonsoftJsonLongId(value); -// var serializedLong = NewtonsoftJsonSerializer.SerializeObject(value); -// -// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedLong); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanDeserializeFromLong_WithSystemTextJsonProvider() -// { -// var value = 123L; -// var foo = new SystemTextJsonLongId(value); -// var serializedLong = SystemTextJsonSerializer.Serialize(value); -// -// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedLong); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanSerializeToLong_WithBothJsonConverters() -// { -// var foo = new BothJsonLongId(123L); -// -// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedLong1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); -// -// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); -// var serializedLong2 = SystemTextJsonSerializer.Serialize(foo.Value); -// -// Assert.Equal(serializedFoo1, serializedLong1); -// Assert.Equal(serializedFoo2, serializedLong2); -// } -// -// [Fact] -// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() -// { -// var foo = new NoJsonLongId(123); -// -// var serialized = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":" + foo.Value + "}"; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() -// { -// var foo = new NoJsonLongId(123); -// -// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); -// -// var expected = $"\"{foo.Value}\""; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoTypeConverter_SerializesWithValueProperty() -// { -// var foo = new NoConverterLongId(123); -// -// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); -// var systemText = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":" + foo.Value + "}"; -// -// Assert.Equal(expected, newtonsoft); -// Assert.Equal(expected, systemText); -// } -// -// [Fact] -// public void WhenEfCoreValueConverterUsesValueConverter() -// { -// var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// var original = new TestEntity { Id = new EfCoreLongId(123) }; -// using (var context = new TestDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add(original); -// context.SaveChanges(); -// } -// -// using (var context = new TestDbContext(options)) -// { -// var all = context.Entities.ToList(); -// var retrieved = Assert.Single(all); -// Assert.Equal(original.Id, retrieved.Id); -// } -// } -// -// [Fact] -// public async Task WhenDapperValueConverterUsesValueConverter() -// { -// using var connection = new SqliteConnection("DataSource=:memory:"); -// await connection.OpenAsync(); -// -// var results = await connection.QueryAsync("SELECT 123"); -// -// var value = Assert.Single(results); -// Assert.Equal(value, new DapperLongId(123)); -// } -// -// [Theory] -// [InlineData(123L)] -// [InlineData("123")] -// public void TypeConverter_CanConvertToAndFrom(object value) -// { -// var converter = TypeDescriptor.GetConverter(typeof(NoJsonLongId)); -// var id = converter.ConvertFrom(value); -// Assert.IsType(id); -// Assert.Equal(new NoJsonLongId(123), id); -// -// var reconverted = converter.ConvertTo(id, value.GetType()); -// Assert.Equal(value, reconverted); -// } -// -// [Fact] -// public void CanCompareDefaults() -// { -// ComparableLongId original = default; -// var other = ComparableLongId.Empty; -// -// var compare1 = original.CompareTo(other); -// var compare2 = other.CompareTo(original); -// Assert.Equal(compare1, -compare2); -// } -// -// [Fact] -// public void CanEquateDefaults() -// { -// EquatableLongId original = default; -// var other = EquatableLongId.Empty; -// -// var equals1 = (original as IEquatable).Equals(other); -// var equals2 = (other as IEquatable).Equals(original); -// -// Assert.Equal(equals1, equals2); -// } -// -// [Fact] -// public void ImplementsInterfaces() -// { -// Assert.IsAssignableFrom>(BothLongId.Empty); -// Assert.IsAssignableFrom>(BothLongId.Empty); -// -// Assert.IsAssignableFrom>(EquatableLongId.Empty); -// Assert.IsAssignableFrom>(ComparableLongId.Empty); -// -// #pragma warning disable 184 -// Assert.False(LongId.Empty is IComparable); -// Assert.False(LongId.Empty is IEquatable); -// #pragma warning restore 184 -// } -// -// -// #if NET6_0_OR_GREATER -// [Fact] -// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() -// { -// var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// using (var context = new ConventionsDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add( -// new TestEntity { Id = new EfCoreLongId(123) }); -// context.SaveChanges(); -// } -// using (var context = new ConventionsDbContext(options)) -// { -// var all = context.Entities.ToList(); -// Assert.Single(all); -// } -// } -// -// public class ConventionsDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public ConventionsDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) -// { -// configurationBuilder -// .Properties() -// .HaveConversion(); -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .ValueGeneratedNever(); -// }); -// } -// } -// #endif -// -// public class TestDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public TestDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .HasConversion(new EfCoreLongId.EfCoreValueConverter()) -// .ValueGeneratedNever(); -// }); -// } -// } -// -// public class TestEntity -// { -// public EfCoreLongId Id { get; set; } -// } -// -// public class EntityWithNullableId -// { -// public NewtonsoftJsonLongId? Id { get; set; } -// } -// } -// } \ No newline at end of file +using System; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; +using Dapper; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using StronglyTypedIds.IntegrationTests.Types; +using Xunit; +using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; + +namespace StronglyTypedIds.IntegrationTests +{ + public class LongIdTests + { + [Fact] + public void SameValuesAreEqual() + { + var id = 123L; + var foo1 = new LongId(id); + var foo2 = new LongId(id); + + Assert.Equal(foo1, foo2); + } + + [Fact] + public void EmptyValueIsEmpty() + { + Assert.Equal(0, LongId.Empty.Value); + } + + + [Fact] + public void DifferentValuesAreUnequal() + { + var foo1 = new LongId(1L); + var foo2 = new LongId(2L); + + Assert.NotEqual(foo1, foo2); + } + + [Fact] + public void OverloadsWorkCorrectly() + { + var id = 12L; + var same1 = new LongId(id); + var same2 = new LongId(id); + var different = new LongId(3L); + + Assert.True(same1 == same2); + Assert.False(same1 == different); + Assert.False(same1 != same2); + Assert.True(same1 != different); + } + + [Fact] + public void DifferentTypesAreUnequal() + { + var bar = GuidId2.New(); + var foo = new LongId(23L); + + //Assert.NotEqual(bar, foo); // does not compile + Assert.NotEqual((object)bar, (object)foo); + } + + [Fact] + public void CanSerializeToLong_WithNewtonsoftJsonProvider() + { + var foo = new ConvertersLongId(123); + + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedLong = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + Assert.Equal(serializedFoo, serializedLong); + } + + [Fact] + public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() + { + var entity = new EntityWithNullableId { Id = null }; + + var json = NewtonsoftJsonSerializer.SerializeObject(entity); + var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); + + Assert.NotNull(deserialize); + Assert.Null(deserialize.Id); + } + + [Fact] + public void CanSerializeToLong_WithSystemTextJsonProvider() + { + var foo = new ConvertersLongId(123L); + + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedLong = SystemTextJsonSerializer.Serialize(foo.Value); + + Assert.Equal(serializedFoo, serializedLong); + } + + [Fact] + public void CanDeserializeFromLong_WithNewtonsoftJsonProvider() + { + var value = 123L; + var foo = new ConvertersLongId(value); + var serializedLong = NewtonsoftJsonSerializer.SerializeObject(value); + + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedLong); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void CanDeserializeFromLong_WithSystemTextJsonProvider() + { + var value = 123L; + var foo = new ConvertersLongId(value); + var serializedLong = SystemTextJsonSerializer.Serialize(value); + + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedLong); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() + { + var foo = new LongId(123); + + var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); + + var expected = $"\"{foo.Value}\""; + + Assert.Equal(expected, serialized); + } + + [Fact] + public void WhenEfCoreValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity { Id = new ConvertersLongId(123) }; + using (var context = new TestDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add(original); + context.SaveChanges(); + } + + using (var context = new TestDbContext(options)) + { + var all = context.Entities.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); + } + } + + [Fact] + public async Task WhenDapperValueConverterUsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + await connection.OpenAsync(); + + var results = await connection.QueryAsync("SELECT 123"); + + var value = Assert.Single(results); + Assert.Equal(value, new ConvertersLongId(123)); + } + + [Theory] + [InlineData(123L)] + [InlineData("123")] + public void TypeConverter_CanConvertToAndFrom(object value) + { + var converter = TypeDescriptor.GetConverter(typeof(LongId)); + var id = converter.ConvertFrom(value); + Assert.IsType(id); + Assert.Equal(new LongId(123), id); + + var reconverted = converter.ConvertTo(id, value.GetType()); + Assert.Equal(value, reconverted); + } + + [Fact] + public void CanCompareDefaults() + { + LongId original = default; + var other = LongId.Empty; + + var compare1 = original.CompareTo(other); + var compare2 = other.CompareTo(original); + Assert.Equal(compare1, -compare2); + } + + [Fact] + public void CanEquateDefaults() + { + LongId original = default; + var other = LongId.Empty; + + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); + + Assert.Equal(equals1, equals2); + } + + [Fact] + public void ImplementsInterfaces() + { + Assert.IsAssignableFrom>(LongId.Empty); + Assert.IsAssignableFrom>(LongId.Empty); + +#pragma warning disable 184 + Assert.True(LongId.Empty is IComparable); + Assert.True(LongId.Empty is IEquatable); +#pragma warning restore 184 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(IntId.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs("123"); + ParseSpan("123".AsSpan()); + + T ParseAs(string s) where T : IParsable + { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + { + return T.Parse(s, null); + } +#endif + } + + +#if NET6_0_OR_GREATER + [Fact] + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add( + new TestEntity { Id = new ConvertersLongId(123) }); + context.SaveChanges(); + } + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + Assert.Single(all); + } + } + + internal class ConventionsDbContext : DbContext + { + public DbSet Entities { get; set; } + + public ConventionsDbContext(DbContextOptions options) : base(options) + { + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + configurationBuilder + .Properties() + .HaveConversion(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); + } + } +#endif + + internal class TestDbContext : DbContext + { + public DbSet Entities { get; set; } + + public TestDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .HasConversion(new ConvertersLongId.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); + } + } + + internal class TestEntity + { + public ConvertersLongId Id { get; set; } + } + + internal class EntityWithNullableId + { + public ConvertersLongId? Id { get; set; } + } + } +} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj b/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj index 6ff0daea3..00a218283 100644 --- a/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj +++ b/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1;net5.0;net6.0;net7.0 + netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 net48;$(TargetFrameworks) false true diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Core3_1.received.txt deleted file mode 100644 index d0568badd..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Core3_1.received.txt +++ /dev/null @@ -1,522 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet6_0.received.txt deleted file mode 100644 index d0568badd..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet6_0.received.txt +++ /dev/null @@ -1,522 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet7_0.received.txt deleted file mode 100644 index d0568badd..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.DotNet7_0.received.txt +++ /dev/null @@ -1,522 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Net4_8.received.txt deleted file mode 100644 index d0568badd..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.Net4_8.received.txt +++ /dev/null @@ -1,522 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index 8ab8ff518..d0568badd 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -321,13 +321,14 @@ namespace StronglyTypedIds #nullable enable [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + partial struct MyId : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_0_OR_GREATER - ,global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public global::System.Guid Value { get; } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Core3_1.received.txt deleted file mode 100644 index 58ec20237..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Core3_1.received.txt +++ /dev/null @@ -1,532 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass where T: new() - { - internal partial record InnerClass - { - public partial struct InnerStruct - { - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt deleted file mode 100644 index 58ec20237..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt +++ /dev/null @@ -1,532 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass where T: new() - { - internal partial record InnerClass - { - public partial struct InnerStruct - { - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt deleted file mode 100644 index 58ec20237..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt +++ /dev/null @@ -1,532 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass where T: new() - { - internal partial record InnerClass - { - public partial struct InnerStruct - { - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Net4_8.received.txt deleted file mode 100644 index 58ec20237..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.Net4_8.received.txt +++ /dev/null @@ -1,532 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass where T: new() - { - internal partial record InnerClass - { - public partial struct InnerStruct - { - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt index 72641679d..58ec20237 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -327,13 +327,14 @@ namespace SomeNamespace { public partial struct InnerStruct { - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + partial struct MyId : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_0_OR_GREATER - ,global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public global::System.Guid Value { get; } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Core3_1.received.txt deleted file mode 100644 index d7ab88402..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Core3_1.received.txt +++ /dev/null @@ -1,525 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet6_0.received.txt deleted file mode 100644 index d7ab88402..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet6_0.received.txt +++ /dev/null @@ -1,525 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet7_0.received.txt deleted file mode 100644 index d7ab88402..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.DotNet7_0.received.txt +++ /dev/null @@ -1,525 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Net4_8.received.txt deleted file mode 100644 index d7ab88402..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.Net4_8.received.txt +++ /dev/null @@ -1,525 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index d4e31ce30..d7ab88402 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -323,13 +323,14 @@ namespace SomeNamespace { [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + partial struct MyId : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_0_OR_GREATER - ,global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public global::System.Guid Value { get; } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Core3_1.received.txt deleted file mode 100644 index d7ab88402..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Core3_1.received.txt +++ /dev/null @@ -1,525 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet6_0.received.txt deleted file mode 100644 index d7ab88402..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet6_0.received.txt +++ /dev/null @@ -1,525 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt deleted file mode 100644 index d7ab88402..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.DotNet7_0.received.txt +++ /dev/null @@ -1,525 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Net4_8.received.txt deleted file mode 100644 index d7ab88402..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.Net4_8.received.txt +++ /dev/null @@ -1,525 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index d4e31ce30..d7ab88402 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -323,13 +323,14 @@ namespace SomeNamespace { [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + partial struct MyId : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_0_OR_GREATER - ,global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public global::System.Guid Value { get; } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Core3_1.received.txt deleted file mode 100644 index 6e46018a3..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Core3_1.received.txt +++ /dev/null @@ -1,742 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace MyContracts.V1 -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} - -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace MyContracts.V2 -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet6_0.received.txt deleted file mode 100644 index 6e46018a3..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet6_0.received.txt +++ /dev/null @@ -1,742 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace MyContracts.V1 -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} - -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace MyContracts.V2 -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet7_0.received.txt deleted file mode 100644 index 6e46018a3..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.DotNet7_0.received.txt +++ /dev/null @@ -1,742 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace MyContracts.V1 -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} - -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace MyContracts.V2 -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Net4_8.received.txt deleted file mode 100644 index 6e46018a3..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.Net4_8.received.txt +++ /dev/null @@ -1,742 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace MyContracts.V1 -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} - -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace MyContracts.V2 -{ - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Core3_1.received.txt deleted file mode 100644 index 6197b7590..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Core3_1.received.txt +++ /dev/null @@ -1,528 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass - { - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet6_0.received.txt deleted file mode 100644 index 6197b7590..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet6_0.received.txt +++ /dev/null @@ -1,528 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass - { - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet7_0.received.txt deleted file mode 100644 index 6197b7590..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.DotNet7_0.received.txt +++ /dev/null @@ -1,528 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass - { - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Net4_8.received.txt deleted file mode 100644 index 6197b7590..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.Net4_8.received.txt +++ /dev/null @@ -1,528 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass - { - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index fc77f9d25..6197b7590 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -325,13 +325,14 @@ namespace SomeNamespace { [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + partial struct MyId : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_0_OR_GREATER - ,global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public global::System.Guid Value { get; } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index cc5be7be6..3b50d0609 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -351,7 +351,7 @@ namespace SomeNamespace public override int GetHashCode() => Value.GetHashCode(); - public override string ToString() => Value.ToString(); + public override string ToString() => Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); @@ -392,7 +392,7 @@ namespace SomeNamespace if (destinationType == typeof(string)) { - return idValue.Value.ToString(); + return idValue.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Core3_1.received.txt deleted file mode 100644 index 7609f784c..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Core3_1.received.txt +++ /dev/null @@ -1,534 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass - { - internal partial record InnerClass - { - public readonly partial record InnerStruct - { - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt deleted file mode 100644 index 7609f784c..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet6_0.received.txt +++ /dev/null @@ -1,534 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass - { - internal partial record InnerClass - { - public readonly partial record InnerStruct - { - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt deleted file mode 100644 index 7609f784c..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.DotNet7_0.received.txt +++ /dev/null @@ -1,534 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass - { - internal partial record InnerClass - { - public readonly partial record InnerStruct - { - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Net4_8.received.txt deleted file mode 100644 index 7609f784c..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.Net4_8.received.txt +++ /dev/null @@ -1,534 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -namespace SomeNamespace -{ - public partial class ParentClass - { - internal partial record InnerClass - { - public readonly partial record InnerStruct - { - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } - } - } - } -} diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index 90f845d71..7609f784c 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -329,13 +329,14 @@ namespace SomeNamespace { [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + partial struct MyId : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_0_OR_GREATER - ,global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public global::System.Guid Value { get; } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Core3_1.received.txt deleted file mode 100644 index 4da683f8a..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Core3_1.received.txt +++ /dev/null @@ -1,517 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public int Value { get; } - - public MyId(int value) - { - Value = value; - } - - public static readonly MyId Empty = new MyId(0); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - int intValue => new MyId(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(int)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetInt32()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteNumberValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt32()); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); -#endif - } - - public static MyId Parse(string input) - => new(int.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(int.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (int.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - - result = default; - return false; - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(int.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(int.Parse(input, provider)); -#else - => new(int.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (int.TryParse(input, provider, out var guid)) -#else - if (int.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - - result = default; - return false; - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet6_0.received.txt deleted file mode 100644 index 4da683f8a..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet6_0.received.txt +++ /dev/null @@ -1,517 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public int Value { get; } - - public MyId(int value) - { - Value = value; - } - - public static readonly MyId Empty = new MyId(0); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - int intValue => new MyId(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(int)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetInt32()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteNumberValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt32()); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); -#endif - } - - public static MyId Parse(string input) - => new(int.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(int.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (int.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - - result = default; - return false; - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(int.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(int.Parse(input, provider)); -#else - => new(int.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (int.TryParse(input, provider, out var guid)) -#else - if (int.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - - result = default; - return false; - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet7_0.received.txt deleted file mode 100644 index 4da683f8a..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.DotNet7_0.received.txt +++ /dev/null @@ -1,517 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public int Value { get; } - - public MyId(int value) - { - Value = value; - } - - public static readonly MyId Empty = new MyId(0); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - int intValue => new MyId(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(int)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetInt32()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteNumberValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt32()); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); -#endif - } - - public static MyId Parse(string input) - => new(int.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(int.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (int.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - - result = default; - return false; - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(int.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(int.Parse(input, provider)); -#else - => new(int.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (int.TryParse(input, provider, out var guid)) -#else - if (int.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - - result = default; - return false; - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Net4_8.received.txt deleted file mode 100644 index 4da683f8a..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.Net4_8.received.txt +++ /dev/null @@ -1,517 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public int Value { get; } - - public MyId(int value) - { - Value = value; - } - - public static readonly MyId Empty = new MyId(0); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - int intValue => new MyId(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(int)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetInt32()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteNumberValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt32()); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); -#endif - } - - public static MyId Parse(string input) - => new(int.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(int.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (int.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - - result = default; - return false; - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(int.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(int.Parse(input, provider)); -#else - => new(int.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (int.TryParse(input, provider, out var guid)) -#else - if (int.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - - result = default; - return false; - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index 47135128d..97406b9e9 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -321,13 +321,14 @@ namespace StronglyTypedIds #nullable enable [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + partial struct MyId : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public int Value { get; } @@ -348,7 +349,7 @@ namespace StronglyTypedIds public override int GetHashCode() => Value.GetHashCode(); - public override string ToString() => Value.ToString(); + public override string ToString() => Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); @@ -389,7 +390,7 @@ namespace StronglyTypedIds if (destinationType == typeof(string)) { - return idValue.Value.ToString(); + return idValue.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Core3_1.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Core3_1.received.txt deleted file mode 100644 index d0568badd..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Core3_1.received.txt +++ /dev/null @@ -1,522 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet6_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet6_0.received.txt deleted file mode 100644 index d0568badd..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet6_0.received.txt +++ /dev/null @@ -1,522 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet7_0.received.txt deleted file mode 100644 index d0568badd..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.DotNet7_0.received.txt +++ /dev/null @@ -1,522 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Net4_8.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Net4_8.received.txt deleted file mode 100644 index d0568badd..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.Net4_8.received.txt +++ /dev/null @@ -1,522 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt index 8ab8ff518..d0568badd 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt @@ -321,13 +321,14 @@ namespace StronglyTypedIds #nullable enable [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable + partial struct MyId : #if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_0_OR_GREATER - ,global::System.IParsable, global::System.ISpanParsable + global::System.ISpanFormattable, #endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { public global::System.Guid Value { get; } From 485b1181a6f8a171ac905ceae74fc1ff3350528e Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Thu, 2 Nov 2023 23:11:07 +0000 Subject: [PATCH 05/47] Add string (and fix bugs) --- src/StronglyTypedIds/EmbeddedSources.Int.cs | 12 +- src/StronglyTypedIds/EmbeddedSources.Long.cs | 12 +- .../EmbeddedSources.String.cs | 190 +++++ src/StronglyTypedIds/EmbeddedSources.cs | 1 + .../Templates/int-full.typedid | 4 +- .../Templates/long-full.typedid | 4 +- .../Templates/string-full.typedid | 237 ++++++ .../DapperTypeHandlers.cs | 2 +- .../Enums.cs | 35 +- .../LongIdTests.cs | 2 + .../StringIdTests.cs | 705 +++++++++--------- 11 files changed, 816 insertions(+), 388 deletions(-) create mode 100644 src/StronglyTypedIds/EmbeddedSources.String.cs create mode 100644 src/StronglyTypedIds/Templates/string-full.typedid diff --git a/src/StronglyTypedIds/EmbeddedSources.Int.cs b/src/StronglyTypedIds/EmbeddedSources.Int.cs index 6d44ba12c..8ec6e1bc3 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Int.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Int.cs @@ -120,9 +120,9 @@ public static bool TryParse( return false; } - if (int.TryParse(input, provider, out var guid)) + if (int.TryParse(input, provider, out var value)) { - result = new(guid); + result = new(value); return true; } @@ -134,7 +134,7 @@ public static bool TryParse( /// public string ToString( #if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)] #endif string? format, global::System.IFormatProvider? formatProvider) @@ -162,12 +162,12 @@ public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, globa public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) { #if NET7_0_OR_GREATER - if (int.TryParse(input, provider, out var guid)) + if (int.TryParse(input, provider, out var value)) #else - if (int.TryParse(input, out var guid)) + if (int.TryParse(input, out var value)) #endif { - result = new(guid); + result = new(value); return true; } diff --git a/src/StronglyTypedIds/EmbeddedSources.Long.cs b/src/StronglyTypedIds/EmbeddedSources.Long.cs index ab79bb335..09e9271f0 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Long.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Long.cs @@ -120,9 +120,9 @@ public static bool TryParse( return false; } - if (long.TryParse(input, provider, out var guid)) + if (long.TryParse(input, provider, out var value)) { - result = new(guid); + result = new(value); return true; } @@ -134,7 +134,7 @@ public static bool TryParse( /// public string ToString( #if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)] #endif string? format, global::System.IFormatProvider? formatProvider) @@ -162,12 +162,12 @@ public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, globa public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) { #if NET7_0_OR_GREATER - if (long.TryParse(input, provider, out var guid)) + if (long.TryParse(input, provider, out var value)) #else - if (long.TryParse(input, out var guid)) + if (long.TryParse(input, out var value)) #endif { - result = new(guid); + result = new(value); return true; } diff --git a/src/StronglyTypedIds/EmbeddedSources.String.cs b/src/StronglyTypedIds/EmbeddedSources.String.cs new file mode 100644 index 000000000..74c0e3a53 --- /dev/null +++ b/src/StronglyTypedIds/EmbeddedSources.String.cs @@ -0,0 +1,190 @@ +namespace StronglyTypedIds; + +internal static partial class EmbeddedSources +{ + private const string StringTemplate = """ + partial struct PLACEHOLDERID : + #if NET6_0_OR_GREATER + global::System.ISpanFormattable, + #endif + #if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, + #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public string Value { get; } + + public PLACEHOLDERID(string value) + { + Value = value ?? throw new global::System.ArgumentNullException(nameof(value)); + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(string.Empty); + + /// + public bool Equals(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => true, + (null, _) => false, + (_, null) => false, + (_, _) => Value.Equals(other.Value), + }; + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value; + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => 0, + (null, _) => -1, + (_, null) => 1, + (_, _) => Value.CompareTo(other.Value), + }; + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + if (value is string stringValue) + { + return new PLACEHOLDERID(stringValue); + } + + return base.ConvertFrom(context, culture, value); + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(string)) + { + return idValue.Value; + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetString()!); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + + #if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetString()!); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value); + #endif + } + + public static PLACEHOLDERID Parse(string input) + => new(input); + + #if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(input); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + result = new(input); + return true; + } + #endif + + /// + public string ToString(string? format, global::System.IFormatProvider? formatProvider) + => Value; + + #if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(input.ToString()); + #endif + + #if NET6_0_OR_GREATER + #if NET7_0_OR_GREATER + /// + #endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) + => new(input.ToString()); + + #if NET7_0_OR_GREATER + /// + #endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { + result = new(input.ToString()); + return true; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format = default) + { + if (destination.Length > Value.Length) + { + global::System.MemoryExtensions.AsSpan(Value).CopyTo(destination); + charsWritten = Value.Length; + return true; + } + + charsWritten = default; + return false; + } + #endif + } + """; +} \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.cs b/src/StronglyTypedIds/EmbeddedSources.cs index 77bbf922c..9ae8cae86 100644 --- a/src/StronglyTypedIds/EmbeddedSources.cs +++ b/src/StronglyTypedIds/EmbeddedSources.cs @@ -23,6 +23,7 @@ internal static string GetTemplate(Template template) Template.Guid => GuidTemplate, Template.Int => IntTemplate, Template.Long => LongTemplate, + Template.String => StringTemplate, _ => string.Empty, }; diff --git a/src/StronglyTypedIds/Templates/int-full.typedid b/src/StronglyTypedIds/Templates/int-full.typedid index f2dfcfce0..f6abd5a6a 100644 --- a/src/StronglyTypedIds/Templates/int-full.typedid +++ b/src/StronglyTypedIds/Templates/int-full.typedid @@ -116,9 +116,9 @@ return false; } - if (int.TryParse(input, provider, out var guid)) + if (int.TryParse(input, provider, out var value)) { - result = new(guid); + result = new(value); return true; } diff --git a/src/StronglyTypedIds/Templates/long-full.typedid b/src/StronglyTypedIds/Templates/long-full.typedid index 55d094b4b..5818fdd28 100644 --- a/src/StronglyTypedIds/Templates/long-full.typedid +++ b/src/StronglyTypedIds/Templates/long-full.typedid @@ -116,9 +116,9 @@ return false; } - if (long.TryParse(input, provider, out var guid)) + if (long.TryParse(input, provider, out var value)) { - result = new(guid); + result = new(value); return true; } diff --git a/src/StronglyTypedIds/Templates/string-full.typedid b/src/StronglyTypedIds/Templates/string-full.typedid new file mode 100644 index 000000000..ac6201e45 --- /dev/null +++ b/src/StronglyTypedIds/Templates/string-full.typedid @@ -0,0 +1,237 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public string Value { get; } + + public PLACEHOLDERID(string value) + { + Value = value ?? throw new global::System.ArgumentNullException(nameof(value)); + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(string.Empty); + + /// + public bool Equals(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => true, + (null, _) => false, + (_, null) => false, + (_, _) => Value.Equals(other.Value), + }; + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value; + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => 0, + (null, _) => -1, + (_, null) => 1, + (_, _) => Value.CompareTo(other.Value), + }; + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + if (value is string stringValue) + { + return new PLACEHOLDERID(stringValue); + } + + return base.ConvertFrom(context, culture, value); + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(string)) + { + return idValue.Value; + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetString()!); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetString()!); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(input); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(input); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + result = new(input); + return true; + } +#endif + + /// + public string ToString(string? format, global::System.IFormatProvider? formatProvider) + => Value; + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(input.ToString()); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) + => new(input.ToString()); + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { + result = new(input.ToString()); + return true; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format = default) + { + if (destination.Length > Value.Length) + { + global::System.MemoryExtensions.AsSpan(Value).CopyTo(destination); + charsWritten = Value.Length; + return true; + } + + charsWritten = default; + return false; + } +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + string stringValue => new PLACEHOLDERID(stringValue), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + if (objectType == typeof(PLACEHOLDERID?)) + { + var value = serializer.Deserialize(reader); + + return value is null ? null : new PLACEHOLDERID(value); + } + + return new PLACEHOLDERID(serializer.Deserialize(reader)!); + } + } + } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs index da182a7e8..61c6a549d 100644 --- a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs +++ b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs @@ -12,7 +12,7 @@ public static void AddHandlers() SqlMapper.AddTypeHandler(new ConvertersGuidId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersIntId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersLongId.DapperTypeHandler()); - // SqlMapper.AddTypeHandler(new DapperStringId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new ConvertersStringId.DapperTypeHandler()); // SqlMapper.AddTypeHandler(new DapperNullableStringId.DapperTypeHandler()); // SqlMapper.AddTypeHandler(new DapperNewIdId.DapperTypeHandler()); } diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index 1b2522517..f349a0dd9 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -1,9 +1,9 @@ -using System.ComponentModel; -using System.Text.Json; -using StronglyTypedIds; #nullable enable +using System; + namespace StronglyTypedIds.IntegrationTests.Types; + [StronglyTypedId] partial struct DefaultId1 { } @@ -33,16 +33,37 @@ partial struct ConvertersLongId { } [StronglyTypedId("newid")] partial struct NewIdId1 { } - + [StronglyTypedId("newid")] public partial struct NewIdId2 { } +[StronglyTypedId(Template.String)] +partial struct StringId +{ + public bool TryFormat2( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format = default) + { + if (destination.Length > Value.Length) + { + MemoryExtensions.AsSpan(Value).CopyTo(destination); + charsWritten = Value.Length; + return true; + } + + charsWritten = default; + return false; + } +} + +[StronglyTypedId("string-full")] +partial struct ConvertersStringId { } + // [StronglyTypedId(Template.NullableString)] // partial struct NullableStringId { } // -// [StronglyTypedId(Template.String)] -// partial struct StringId { } -// + // public partial class SomeType where T : new() // { // public partial record struct NestedType diff --git a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs index a681f045e..495f75c29 100644 --- a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs @@ -216,8 +216,10 @@ public void ImplementsInterfaces() Assert.IsAssignableFrom>(LongId.Empty); #pragma warning disable 184 +#pragma warning disable CS0183 Assert.True(LongId.Empty is IComparable); Assert.True(LongId.Empty is IEquatable); +#pragma warning restore CS0183 #pragma warning restore 184 #if NET6_0_OR_GREATER diff --git a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs index 61a9de288..7e1882365 100644 --- a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs @@ -1,364 +1,341 @@ -// using System; -// using System.ComponentModel; -// using System.Linq; -// using System.Threading.Tasks; -// using Dapper; -// using Microsoft.Data.Sqlite; -// using Microsoft.EntityFrameworkCore; -// using StronglyTypedIds.IntegrationTests.Types; -// using Xunit; -// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; -// -// namespace StronglyTypedIds.IntegrationTests -// { -// public class StringIdTests -// { -// [Fact] -// public async Task ThrowsIfTryToCreateWithNull() -// { -// await Assert.ThrowsAsync(() => Task.FromResult(new StringId(null))); -// } -// -// [Fact] -// public void SameValuesAreEqual() -// { -// var id = "some-value"; -// var foo1 = new StringId(id); -// var foo2 = new StringId(id); -// -// Assert.Equal(foo1, foo2); -// } -// -// [Fact] -// public void EmptyValueIsEmpty() -// { -// Assert.Equal(StringId.Empty.Value, string.Empty); -// } -// -// -// [Fact] -// public void DifferentValuesAreUnequal() -// { -// var foo1 = new StringId("value1"); -// var foo2 = new StringId("value2"); -// -// Assert.NotEqual(foo1, foo2); -// } -// -// [Fact] -// public void OverloadsWorkCorrectly() -// { -// var id = "some-value"; -// var same1 = new StringId(id); -// var same2 = new StringId(id); -// var different = new StringId("other value"); -// -// Assert.True(same1 == same2); -// Assert.False(same1 == different); -// Assert.False(same1 != same2); -// Assert.True(same1 != different); -// } -// -// [Fact] -// public void DifferentTypesAreUnequal() -// { -// var bar = GuidId2.New(); -// var foo = new StringId("Value"); -// -// //Assert.NotEqual(bar, foo); // does not compile -// Assert.NotEqual((object)bar, (object)foo); -// } -// -// [Fact] -// public void CanSerializeToString_WithNewtonsoftJsonProvider() -// { -// var foo = new NewtonsoftJsonStringId("123"); -// -// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); -// -// Assert.Equal(serializedFoo, serializedString); -// } -// -// [Fact] -// public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() -// { -// var entity = new EntityWithNullableId { Id = null }; -// -// var json = NewtonsoftJsonSerializer.SerializeObject(entity); -// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); -// -// Assert.NotNull(deserialize); -// Assert.Null(deserialize.Id); -// } -// -// [Fact] -// public void CanSerializeToString_WithSystemTextJsonProvider() -// { -// var foo = new SystemTextJsonStringId("123"); -// -// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); -// var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); -// -// Assert.Equal(serializedFoo, serializedString); -// } -// -// [Fact] -// public void CanDeserializeFromString_WithNewtonsoftJsonProvider() -// { -// var value = "123"; -// var foo = new NewtonsoftJsonStringId(value); -// var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); -// -// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanDeserializeFromString_WithSystemTextJsonProvider() -// { -// var value = "123"; -// var foo = new SystemTextJsonStringId(value); -// var serializedString = SystemTextJsonSerializer.Serialize(value); -// -// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanSerializeToString_WithBothJsonConverters() -// { -// var foo = new BothJsonStringId("123"); -// -// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedString1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); -// -// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); -// var serializedString2 = SystemTextJsonSerializer.Serialize(foo.Value); -// -// Assert.Equal(serializedFoo1, serializedString1); -// Assert.Equal(serializedFoo2, serializedString2); -// } -// -// [Fact] -// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() -// { -// var foo = new NoJsonStringId("123"); -// -// var serialized = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":\"" + foo.Value + "\"}"; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() -// { -// var foo = new NoJsonStringId("123"); -// -// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); -// -// var expected = "\"" + foo.Value + "\""; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoTypeConverter_SerializesWithValueProperty() -// { -// var foo = new NoConvertersStringId("123"); -// -// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); -// var systemText = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":\"" + foo.Value + "\"}"; -// -// Assert.Equal(expected, newtonsoft); -// Assert.Equal(expected, systemText); -// } -// -// [Fact] -// public void WhenEfCoreValueConverterUsesValueConverter() -// { -// using var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreStringId("some name") }; -// using (var context = new TestDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add(original); -// context.SaveChanges(); -// } -// -// using (var context = new TestDbContext(options)) -// { -// var all = context.Entities.ToList(); -// var retrieved = Assert.Single(all); -// Assert.Equal(original.Id, retrieved.Id); -// Assert.Equal(original.Name, retrieved.Name); -// } -// } -// -// [Fact] -// public async Task WhenDapperValueConverterUsesValueConverter() -// { -// using var connection = new SqliteConnection("DataSource=:memory:"); -// await connection.OpenAsync(); -// -// var results = await connection.QueryAsync("SELECT 'this is a value'"); -// -// var value = Assert.Single(results); -// Assert.Equal(value, new DapperStringId("this is a value")); -// } -// -// [Theory] -// [InlineData("")] -// [InlineData("some value")] -// public void TypeConverter_CanConvertToAndFrom(object value) -// { -// var converter = TypeDescriptor.GetConverter(typeof(NoJsonStringId)); -// var id = converter.ConvertFrom(value); -// Assert.IsType(id); -// Assert.Equal(new NoJsonStringId(value?.ToString()), id); -// -// var reconverted = converter.ConvertTo(id, value.GetType()); -// Assert.Equal(value, reconverted); -// } -// -// [Fact] -// public void CanCompareDefaults() -// { -// ComparableStringId original = default; -// var other = ComparableStringId.Empty; -// -// var compare1 = original.CompareTo(other); -// var compare2 = other.CompareTo(original); -// Assert.Equal(compare1, -compare2); -// } -// -// [Fact] -// public void CanEquateDefaults() -// { -// EquatableStringId original = default; -// var other = EquatableStringId.Empty; -// -// var equals1 = (original as IEquatable).Equals(other); -// var equals2 = (other as IEquatable).Equals(original); -// -// Assert.Equal(equals1, equals2); -// } -// -// [Fact] -// public void ImplementsInterfaces() -// { -// Assert.IsAssignableFrom>(BothStringId.Empty); -// Assert.IsAssignableFrom>(BothStringId.Empty); -// -// Assert.IsAssignableFrom>(EquatableStringId.Empty); -// Assert.IsAssignableFrom>(ComparableStringId.Empty); -// -// #pragma warning disable 184 -// Assert.False(StringId.Empty is IComparable); -// Assert.False(StringId.Empty is IEquatable); -// #pragma warning restore 184 -// } -// -// -// #if NET6_0_OR_GREATER -// [Fact] -// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() -// { -// var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreStringId("some name") }; -// using (var context = new ConventionsDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add(original); -// context.SaveChanges(); -// } -// -// using (var context = new ConventionsDbContext(options)) -// { -// var all = context.Entities.ToList(); -// var retrieved = Assert.Single(all); -// Assert.Equal(original.Id, retrieved.Id); -// Assert.Equal(original.Name, retrieved.Name); -// } -// } -// -// public class ConventionsDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public ConventionsDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) -// { -// configurationBuilder -// .Properties() -// .HaveConversion(); -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .ValueGeneratedNever(); -// }); -// } -// } -// #endif -// -// public class TestDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public TestDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Name) -// .HasConversion(new EfCoreStringId.EfCoreValueConverter()) -// .ValueGeneratedNever(); -// }); -// } -// } -// -// public class TestEntity -// { -// public Guid Id { get; set; } -// public EfCoreStringId Name { get; set; } -// } -// -// public class EntityWithNullableId -// { -// public NewtonsoftJsonStringId? Id { get; set; } -// } -// } -// } \ No newline at end of file +using System; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; +using Dapper; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using StronglyTypedIds.IntegrationTests.Types; +using Xunit; +using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; + +namespace StronglyTypedIds.IntegrationTests +{ + public class StringIdTests + { + [Fact] + public async Task ThrowsIfTryToCreateWithNull() + { + await Assert.ThrowsAsync(() => Task.FromResult(new StringId(null))); + } + + [Fact] + public void SameValuesAreEqual() + { + var id = "some-value"; + var foo1 = new StringId(id); + var foo2 = new StringId(id); + + Assert.Equal(foo1, foo2); + } + + [Fact] + public void EmptyValueIsEmpty() + { + Assert.Equal(StringId.Empty.Value, string.Empty); + } + + + [Fact] + public void DifferentValuesAreUnequal() + { + var foo1 = new StringId("value1"); + var foo2 = new StringId("value2"); + + Assert.NotEqual(foo1, foo2); + } + + [Fact] + public void OverloadsWorkCorrectly() + { + var id = "some-value"; + var same1 = new StringId(id); + var same2 = new StringId(id); + var different = new StringId("other value"); + + Assert.True(same1 == same2); + Assert.False(same1 == different); + Assert.False(same1 != same2); + Assert.True(same1 != different); + } + + [Fact] + public void DifferentTypesAreUnequal() + { + var bar = GuidId2.New(); + var foo = new StringId("Value"); + + //Assert.NotEqual(bar, foo); // does not compile + Assert.NotEqual((object)bar, (object)foo); + } + + [Fact] + public void CanSerializeToString_WithNewtonsoftJsonProvider() + { + var foo = new ConvertersStringId("123"); + + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + Assert.Equal(serializedFoo, serializedString); + } + + [Fact] + public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() + { + var entity = new EntityWithNullableId { Id = null }; + + var json = NewtonsoftJsonSerializer.SerializeObject(entity); + var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); + + Assert.NotNull(deserialize); + Assert.Null(deserialize.Id); + } + + [Fact] + public void CanSerializeToString_WithSystemTextJsonProvider() + { + var foo = new ConvertersStringId("123"); + + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); + + Assert.Equal(serializedFoo, serializedString); + } + + [Fact] + public void CanDeserializeFromString_WithNewtonsoftJsonProvider() + { + var value = "123"; + var foo = new ConvertersStringId(value); + var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); + + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void CanDeserializeFromString_WithSystemTextJsonProvider() + { + var value = "123"; + var foo = new ConvertersStringId(value); + var serializedString = SystemTextJsonSerializer.Serialize(value); + + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() + { + var foo = new ConvertersStringId("123"); + + var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); + + var expected = "\"" + foo.Value + "\""; + + Assert.Equal(expected, serialized); + } + + [Fact] + public void WhenEfCoreValueConverterUsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity { Id = Guid.NewGuid(), Name = new ConvertersStringId("some name") }; + using (var context = new TestDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add(original); + context.SaveChanges(); + } + + using (var context = new TestDbContext(options)) + { + var all = context.Entities.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); + Assert.Equal(original.Name, retrieved.Name); + } + } + + [Fact] + public async Task WhenDapperValueConverterUsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + await connection.OpenAsync(); + + var results = await connection.QueryAsync("SELECT 'this is a value'"); + + var value = Assert.Single(results); + Assert.Equal(value, new ConvertersStringId("this is a value")); + } + + [Theory] + [InlineData("")] + [InlineData("some value")] + public void TypeConverter_CanConvertToAndFrom(object value) + { + var converter = TypeDescriptor.GetConverter(typeof(ConvertersStringId)); + var id = converter.ConvertFrom(value); + Assert.IsType(id); + Assert.Equal(new ConvertersStringId(value?.ToString()), id); + + var reconverted = converter.ConvertTo(id, value.GetType()); + Assert.Equal(value, reconverted); + } + + [Fact] + public void CanCompareDefaults() + { + ConvertersStringId original = default; + var other = ConvertersStringId.Empty; + + var compare1 = original.CompareTo(other); + var compare2 = other.CompareTo(original); + Assert.Equal(compare1, -compare2); + } + + [Fact] + public void CanEquateDefaults() + { + ConvertersStringId original = default; + var other = ConvertersStringId.Empty; + + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); + + Assert.Equal(equals1, equals2); + } + + [Fact] + public void ImplementsInterfaces() + { + Assert.IsAssignableFrom>(StringId.Empty); + Assert.IsAssignableFrom>(StringId.Empty); + +#pragma warning disable 184 +#pragma warning disable CS0183 + Assert.True(StringId.Empty is IComparable); + Assert.True(StringId.Empty is IEquatable); +#pragma warning restore CS0183 +#pragma warning restore 184 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(IntId.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs("123"); + ParseSpan("123".AsSpan()); + + T ParseAs(string s) where T : IParsable + { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + { + return T.Parse(s, null); + } +#endif + } + + +#if NET6_0_OR_GREATER + [Fact] + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity { Id = Guid.NewGuid(), Name = new ConvertersStringId("some name") }; + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add(original); + context.SaveChanges(); + } + + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); + Assert.Equal(original.Name, retrieved.Name); + } + } + + internal class ConventionsDbContext : DbContext + { + public DbSet Entities { get; set; } + + public ConventionsDbContext(DbContextOptions options) : base(options) + { + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + configurationBuilder + .Properties() + .HaveConversion(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); + } + } +#endif + + internal class TestDbContext : DbContext + { + public DbSet Entities { get; set; } + + public TestDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Name) + .HasConversion(new ConvertersStringId.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); + } + } + + internal class TestEntity + { + public Guid Id { get; set; } + public ConvertersStringId Name { get; set; } + } + + internal class EntityWithNullableId + { + public ConvertersStringId? Id { get; set; } + } + } +} \ No newline at end of file From 904113b4b8952ce18e36088c50b8378b8fd78e53 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 3 Nov 2023 20:45:18 +0000 Subject: [PATCH 06/47] Add Nullable String --- .../EmbeddedSources.NullableString.cs | 191 ++++ src/StronglyTypedIds/EmbeddedSources.cs | 1 + .../Templates/nullablestring-full.typedid | 240 +++++ .../DapperTypeHandlers.cs | 2 +- .../Enums.cs | 9 +- .../LongIdTests.cs | 6 +- .../NullableStringIdTests.cs | 827 +++++++++--------- .../StringIdTests.cs | 6 +- 8 files changed, 841 insertions(+), 441 deletions(-) create mode 100644 src/StronglyTypedIds/EmbeddedSources.NullableString.cs create mode 100644 src/StronglyTypedIds/Templates/nullablestring-full.typedid diff --git a/src/StronglyTypedIds/EmbeddedSources.NullableString.cs b/src/StronglyTypedIds/EmbeddedSources.NullableString.cs new file mode 100644 index 000000000..b234a523b --- /dev/null +++ b/src/StronglyTypedIds/EmbeddedSources.NullableString.cs @@ -0,0 +1,191 @@ +namespace StronglyTypedIds; + +internal static partial class EmbeddedSources +{ + private const string NullableStringTemplate = """ + partial struct PLACEHOLDERID : + #if NET6_0_OR_GREATER + global::System.ISpanFormattable, + #endif + #if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, + #endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public string? Value { get; } + + public PLACEHOLDERID(string? value) + { + Value = value; + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(string.Empty); + + /// + public bool Equals(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => true, + (null, _) => false, + (_, null) => false, + (_, _) => Value.Equals(other.Value), + }; + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value?.GetHashCode() ?? 0; + + public override string? ToString() => Value; + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => 0, + (null, _) => -1, + (_, null) => 1, + (_, _) => Value.CompareTo(other.Value), + }; + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + => value switch + { + null => new PLACEHOLDERID(null), + string x => new PLACEHOLDERID(x), + _ => base.ConvertFrom(context, culture, value), + }; + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(string)) + { + return idValue.Value; + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetString()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + { + if (value.Value is null) + { + writer.WriteNullValue(); + } + else + { + writer.WriteStringValue(value.Value); + } + } + + #if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetString()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value ?? string.Empty); + #endif + } + + public static PLACEHOLDERID Parse(string input) + => new(input); + + #if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(input); + + /// + public static bool TryParse( + string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + result = new(input); + return true; + } + #endif + + /// + public string ToString(string? format, global::System.IFormatProvider? formatProvider) + => Value ?? string.Empty; + + #if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(input.ToString()); + #endif + + #if NET6_0_OR_GREATER + #if NET7_0_OR_GREATER + /// + #endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) + => new(input.ToString()); + + #if NET7_0_OR_GREATER + /// + #endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { + result = new(input.ToString()); + return true; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format = default) + { + if (Value is not null && destination.Length > Value.Length) + { + global::System.MemoryExtensions.AsSpan(Value).CopyTo(destination); + charsWritten = Value.Length; + return true; + } + + charsWritten = default; + return false; + } + #endif + } + """; +} \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.cs b/src/StronglyTypedIds/EmbeddedSources.cs index 9ae8cae86..eb26ffde1 100644 --- a/src/StronglyTypedIds/EmbeddedSources.cs +++ b/src/StronglyTypedIds/EmbeddedSources.cs @@ -24,6 +24,7 @@ internal static string GetTemplate(Template template) Template.Int => IntTemplate, Template.Long => LongTemplate, Template.String => StringTemplate, + Template.NullableString => NullableStringTemplate, _ => string.Empty, }; diff --git a/src/StronglyTypedIds/Templates/nullablestring-full.typedid b/src/StronglyTypedIds/Templates/nullablestring-full.typedid new file mode 100644 index 000000000..6a2ede966 --- /dev/null +++ b/src/StronglyTypedIds/Templates/nullablestring-full.typedid @@ -0,0 +1,240 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public string? Value { get; } + + public PLACEHOLDERID(string? value) + { + Value = value; + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(string.Empty); + + /// + public bool Equals(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => true, + (null, _) => false, + (_, null) => false, + (_, _) => Value.Equals(other.Value), + }; + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value?.GetHashCode() ?? 0; + + public override string? ToString() => Value; + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => 0, + (null, _) => -1, + (_, null) => 1, + (_, _) => Value.CompareTo(other.Value), + }; + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + => value switch + { + null => new PLACEHOLDERID(null), + string x => new PLACEHOLDERID(x), + _ => base.ConvertFrom(context, culture, value), + }; + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(string)) + { + return idValue.Value; + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetString()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + { + if (value.Value is null) + { + writer.WriteNullValue(); + } + else + { + writer.WriteStringValue(value.Value); + } + } + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetString()); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value ?? string.Empty); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(input); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(input); + + /// + public static bool TryParse( + string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + result = new(input); + return true; + } +#endif + + /// + public string ToString(string? format, global::System.IFormatProvider? formatProvider) + => Value ?? string.Empty; + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(input.ToString()); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) + => new(input.ToString()); + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { + result = new(input.ToString()); + return true; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format = default) + { + if (Value is not null && destination.Length > Value.Length) + { + global::System.MemoryExtensions.AsSpan(Value).CopyTo(destination); + charsWritten = Value.Length; + return true; + } + + charsWritten = default; + return false; + } +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + null => new PLACEHOLDERID(null), + System.DBNull => new PLACEHOLDERID(null), + string stringValue => new PLACEHOLDERID(stringValue), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + if (objectType == typeof(PLACEHOLDERID?)) + { + var value = serializer.Deserialize(reader); + + return new PLACEHOLDERID(value); + } + + return new PLACEHOLDERID(serializer.Deserialize(reader)); + } + } + } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs index 61c6a549d..0a1e7cfa1 100644 --- a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs +++ b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs @@ -13,7 +13,7 @@ public static void AddHandlers() SqlMapper.AddTypeHandler(new ConvertersIntId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersLongId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersStringId.DapperTypeHandler()); - // SqlMapper.AddTypeHandler(new DapperNullableStringId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new ConvertersNullableStringId.DapperTypeHandler()); // SqlMapper.AddTypeHandler(new DapperNewIdId.DapperTypeHandler()); } } diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index f349a0dd9..9e4bc65c0 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -60,9 +60,12 @@ public bool TryFormat2( [StronglyTypedId("string-full")] partial struct ConvertersStringId { } -// [StronglyTypedId(Template.NullableString)] -// partial struct NullableStringId { } -// +[StronglyTypedId(Template.NullableString)] +partial struct NullableStringId { } + +[StronglyTypedId("nullablestring-full")] +partial struct ConvertersNullableStringId { } + // public partial class SomeType where T : new() // { diff --git a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs index 495f75c29..637bb5120 100644 --- a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs @@ -223,12 +223,12 @@ public void ImplementsInterfaces() #pragma warning restore 184 #if NET6_0_OR_GREATER - Assert.IsAssignableFrom(IntId.Empty); + Assert.IsAssignableFrom(LongId.Empty); #endif #if NET7_0_OR_GREATER // doesn't compile if doesn't implement it - ParseAs("123"); - ParseSpan("123".AsSpan()); + ParseAs("123"); + ParseSpan("123".AsSpan()); T ParseAs(string s) where T : IParsable { diff --git a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs index 906e9367e..d1666148c 100644 --- a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs @@ -1,431 +1,396 @@ -// using System; -// using System.ComponentModel; -// using System.Linq; -// using System.Threading.Tasks; -// using Dapper; -// using Microsoft.Data.Sqlite; -// using Microsoft.EntityFrameworkCore; -// using StronglyTypedIds.IntegrationTests.Types; -// using Xunit; -// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; -// -// namespace StronglyTypedIds.IntegrationTests -// { -// public class NullableStringIdTests -// { -// [Fact] -// public void SameValuesAreEqual() -// { -// var id = "some-value"; -// var foo1 = new NullableStringId(id); -// var foo2 = new NullableStringId(id); -// -// Assert.Equal(foo1, foo2); -// } -// -// [Fact] -// public void EmptyValueIsEmpty() -// { -// Assert.Equal(NullableStringId.Empty.Value, string.Empty); -// } -// -// -// [Fact] -// public void DifferentValuesAreUnequal() -// { -// var foo1 = new NullableStringId("value1"); -// var foo2 = new NullableStringId("value2"); -// -// Assert.NotEqual(foo1, foo2); -// } -// -// [Fact] -// public void OverloadsWorkCorrectly() -// { -// var id = "some-value"; -// var same1 = new NullableStringId(id); -// var same2 = new NullableStringId(id); -// var different = new NullableStringId("other value"); -// -// Assert.True(same1 == same2); -// Assert.False(same1 == different); -// Assert.False(same1 != same2); -// Assert.True(same1 != different); -// } -// -// [Fact] -// public void DifferentTypesAreUnequal() -// { -// var bar = GuidId2.New(); -// var foo = new NullableStringId("Value"); -// -// //Assert.NotEqual(bar, foo); // does not compile -// Assert.NotEqual((object)bar, (object)foo); -// } -// -// [Fact] -// public void CanSerializeToString_WithNewtonsoftJsonProvider() -// { -// var foo = new NewtonsoftJsonNullableStringId("123"); -// -// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); -// -// Assert.Equal(serializedFoo, serializedString); -// } -// -// [Fact] -// public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() -// { -// var entity = new EntityWithNullableId { Id = null }; -// -// var json = NewtonsoftJsonSerializer.SerializeObject(entity); -// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); -// -// Assert.NotNull(deserialize); -// // Note the different behaviour from String ID - this will _always_ deserialize to an ID -// Assert.NotNull(deserialize.Id); -// Assert.Null(deserialize.Id.Value.Value); -// } -// -// [Fact] -// public void CanSerializeToString_WithSystemTextJsonProvider() -// { -// var foo = new SystemTextJsonNullableStringId("123"); -// -// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); -// var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); -// -// Assert.Equal(serializedFoo, serializedString); -// } -// -// [Fact] -// public void CanDeserializeFromString_WithNewtonsoftJsonProvider() -// { -// var value = "123"; -// var foo = new NewtonsoftJsonNullableStringId(value); -// var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); -// -// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanDeserializeFromString_WithSystemTextJsonProvider() -// { -// var value = "123"; -// var foo = new SystemTextJsonNullableStringId(value); -// var serializedString = SystemTextJsonSerializer.Serialize(value); -// -// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanSerializeToString_WithBothJsonConverters() -// { -// var foo = new BothJsonNullableStringId("123"); -// -// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedString1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); -// -// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); -// var serializedString2 = SystemTextJsonSerializer.Serialize(foo.Value); -// -// Assert.Equal(serializedFoo1, serializedString1); -// Assert.Equal(serializedFoo2, serializedString2); -// } -// -// [Fact] -// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() -// { -// var foo = new NoJsonNullableStringId("123"); -// -// var serialized = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":\"" + foo.Value + "\"}"; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() -// { -// var foo = new NoJsonNullableStringId("123"); -// -// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); -// -// var expected = "\"" + foo.Value + "\""; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoTypeConverter_SerializesWithValueProperty() -// { -// var foo = new NoConvertersNullableStringId("123"); -// -// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); -// var systemText = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":\"" + foo.Value + "\"}"; -// -// Assert.Equal(expected, newtonsoft); -// Assert.Equal(expected, systemText); -// } -// -// [Fact] -// public void WhenEfCoreValueConverterUsesValueConverter() -// { -// using var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreNullableStringId("some name") }; -// using (var context = new TestDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add(original); -// context.SaveChanges(); -// } -// -// using (var context = new TestDbContext(options)) -// { -// var all = context.Entities.ToList(); -// var retrieved = Assert.Single(all); -// Assert.Equal(original.Id, retrieved.Id); -// Assert.Equal(original.Name, retrieved.Name); -// } -// } -// -// [Fact] -// public async Task WhenDapperValueConverterUsesValueConverter() -// { -// using var connection = new SqliteConnection("DataSource=:memory:"); -// await connection.OpenAsync(); -// -// var results = await connection.QueryAsync("SELECT 'this is a value'"); -// -// var value = Assert.Single(results); -// Assert.Equal(value, new DapperNullableStringId("this is a value")); -// } -// -// [Theory] -// [InlineData("")] -// [InlineData("some value")] -// public void TypeConverter_CanConvertToAndFrom(object value) -// { -// var converter = TypeDescriptor.GetConverter(typeof(NoJsonNullableStringId)); -// var id = converter.ConvertFrom(value); -// Assert.IsType(id); -// Assert.Equal(new NoJsonNullableStringId(value?.ToString()), id); -// -// var reconverted = converter.ConvertTo(id, value.GetType()); -// Assert.Equal(value, reconverted); -// } -// -// [Fact] -// public void CanCompareDefaults() -// { -// ComparableNullableStringId original = default; -// var other = ComparableNullableStringId.Empty; -// -// var compare1 = original.CompareTo(other); -// var compare2 = other.CompareTo(original); -// Assert.Equal(compare1, -compare2); -// } -// -// [Fact] -// public void CanEquateDefaults() -// { -// EquatableNullableStringId original = default; -// var other = EquatableNullableStringId.Empty; -// -// var equals1 = (original as IEquatable).Equals(other); -// var equals2 = (other as IEquatable).Equals(original); -// -// Assert.Equal(equals1, equals2); -// } -// -// [Fact] -// public void ImplementsInterfaces() -// { -// Assert.IsAssignableFrom>(BothNullableStringId.Empty); -// Assert.IsAssignableFrom>(BothNullableStringId.Empty); -// -// Assert.IsAssignableFrom>(EquatableNullableStringId.Empty); -// Assert.IsAssignableFrom>(ComparableNullableStringId.Empty); -// -// #pragma warning disable 184 -// Assert.False(NullableStringId.Empty is IComparable); -// Assert.False(NullableStringId.Empty is IEquatable); -// #pragma warning restore 184 -// } -// -// [Fact] -// public void NullValueIsNull() -// { -// var value = new NullableStringId(null); -// Assert.Null(value.Value); -// } -// -// [Fact] -// public void CanEquateNullableValues() -// { -// var value1 = new NullableStringId(null); -// var value2 = new NullableStringId(null); -// var value3 = new NullableStringId(string.Empty); -// -// Assert.True(value1.Equals(value2)); -// Assert.True(value1.Equals((object)value2)); -// -// Assert.False(value1.Equals(value3)); -// Assert.False(value1.Equals((object)value3)); -// Assert.False(value3.Equals((object)value1)); -// } -// -// [Fact] -// public void NullHashCodes() -// { -// var value1 = new NullableStringId(null); -// var value2 = new NullableStringId(null); -// var value3 = new NullableStringId("something"); -// var value4 = new NullableStringId(string.Empty); -// -// Assert.Equal(value1.GetHashCode(), value2.GetHashCode()); -// Assert.NotEqual(value1.GetHashCode(), value3.GetHashCode()); -// Assert.NotEqual(value1.GetHashCode(), value4.GetHashCode()); -// } -// -// [Fact] -// public void NullSerializesAsExpectedWithoutConverters() -// { -// var expected = "{\"Value\":null}"; -// var value = new NoConvertersNullableStringId(null); -// -// var json = SystemTextJsonSerializer.Serialize(value); -// var systemText = SystemTextJsonSerializer.Serialize(value); -// Assert.Equal(expected, json); -// Assert.Equal(expected, systemText); -// } -// -// [Fact] -// public void NullSerializesAsExpectedWithConverters() -// { -// var expected = "null"; -// var value = new BothJsonNullableStringId(null); -// -// var json = SystemTextJsonSerializer.Serialize(value); -// var systemText = SystemTextJsonSerializer.Serialize(value); -// Assert.Equal(expected, systemText); -// Assert.Equal(expected, json); -// } -// -// [Fact] -// public void TypeConverterConvertsNullAsExpected() -// { -// var converter = TypeDescriptor.GetConverter(typeof(NoJsonNullableStringId)); -// var id = converter.ConvertFrom(null); -// Assert.IsType(id); -// Assert.Equal(new NoJsonNullableStringId(null), id); -// -// var reconverted = converter.ConvertTo(id, typeof(string)); -// Assert.Null(reconverted); -// } -// -// #if NET6_0_OR_GREATER -// [Fact] -// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() -// { -// var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// var original = new TestEntity { Id = Guid.NewGuid(), Name = new EfCoreNullableStringId("some name") }; -// using (var context = new ConventionsDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add(original); -// context.SaveChanges(); -// } -// -// using (var context = new ConventionsDbContext(options)) -// { -// var all = context.Entities.ToList(); -// var retrieved = Assert.Single(all); -// Assert.Equal(original.Id, retrieved.Id); -// Assert.Equal(original.Name, retrieved.Name); -// } -// } -// -// public class ConventionsDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public ConventionsDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) -// { -// configurationBuilder -// .Properties() -// .HaveConversion(); -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .ValueGeneratedNever(); -// }); -// } -// } -// #endif -// -// public class TestDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public TestDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Name) -// .HasConversion(new EfCoreNullableStringId.EfCoreValueConverter()) -// .ValueGeneratedNever(); -// }); -// } -// } -// -// public class TestEntity -// { -// public Guid Id { get; set; } -// public EfCoreNullableStringId Name { get; set; } -// } -// -// -// public class EntityWithNullableId -// { -// public NewtonsoftJsonNullableStringId? Id { get; set; } -// } -// } -// } \ No newline at end of file +using System; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; +using Dapper; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using StronglyTypedIds.IntegrationTests.Types; +using Xunit; +using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; + +namespace StronglyTypedIds.IntegrationTests +{ + public class NullableStringIdTests + { + [Fact] + public void SameValuesAreEqual() + { + var id = "some-value"; + var foo1 = new NullableStringId(id); + var foo2 = new NullableStringId(id); + + Assert.Equal(foo1, foo2); + } + + [Fact] + public void EmptyValueIsEmpty() + { + Assert.Equal(NullableStringId.Empty.Value, string.Empty); + } + + + [Fact] + public void DifferentValuesAreUnequal() + { + var foo1 = new NullableStringId("value1"); + var foo2 = new NullableStringId("value2"); + + Assert.NotEqual(foo1, foo2); + } + + [Fact] + public void OverloadsWorkCorrectly() + { + var id = "some-value"; + var same1 = new NullableStringId(id); + var same2 = new NullableStringId(id); + var different = new NullableStringId("other value"); + + Assert.True(same1 == same2); + Assert.False(same1 == different); + Assert.False(same1 != same2); + Assert.True(same1 != different); + } + + [Fact] + public void DifferentTypesAreUnequal() + { + var bar = GuidId2.New(); + var foo = new NullableStringId("Value"); + + //Assert.NotEqual(bar, foo); // does not compile + Assert.NotEqual((object)bar, (object)foo); + } + + [Fact] + public void CanSerializeToString_WithNewtonsoftJsonProvider() + { + var foo = new ConvertersNullableStringId("123"); + + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + Assert.Equal(serializedFoo, serializedString); + } + + [Fact] + public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() + { + var entity = new EntityWithNullableId { Id = null }; + + var json = NewtonsoftJsonSerializer.SerializeObject(entity); + var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); + + Assert.NotNull(deserialize); + // Note the different behaviour from String ID - this will _always_ deserialize to an ID + Assert.NotNull(deserialize.Id); + Assert.Null(deserialize.Id.Value.Value); + } + + [Fact] + public void CanSerializeToString_WithSystemTextJsonProvider() + { + var foo = new ConvertersNullableStringId("123"); + + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); + + Assert.Equal(serializedFoo, serializedString); + } + + [Fact] + public void CanDeserializeFromString_WithNewtonsoftJsonProvider() + { + var value = "123"; + var foo = new ConvertersNullableStringId(value); + var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); + + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void CanDeserializeFromString_WithSystemTextJsonProvider() + { + var value = "123"; + var foo = new ConvertersNullableStringId(value); + var serializedString = SystemTextJsonSerializer.Serialize(value); + + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() + { + var foo = new ConvertersNullableStringId("123"); + + var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); + + var expected = "\"" + foo.Value + "\""; + + Assert.Equal(expected, serialized); + } + + [Fact] + public void WhenEfCoreValueConverterUsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity { Id = Guid.NewGuid(), Name = new ConvertersNullableStringId("some name") }; + using (var context = new TestDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add(original); + context.SaveChanges(); + } + + using (var context = new TestDbContext(options)) + { + var all = context.Entities.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); + Assert.Equal(original.Name, retrieved.Name); + } + } + + [Fact] + public async Task WhenDapperValueConverterUsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + await connection.OpenAsync(); + + var results = await connection.QueryAsync("SELECT 'this is a value'"); + + var value = Assert.Single(results); + Assert.Equal(value, new ConvertersNullableStringId("this is a value")); + } + + [Theory] + [InlineData("")] + [InlineData("some value")] + public void TypeConverter_CanConvertToAndFrom(object value) + { + var converter = TypeDescriptor.GetConverter(typeof(ConvertersNullableStringId)); + var id = converter.ConvertFrom(value); + Assert.IsType(id); + Assert.Equal(new ConvertersNullableStringId(value?.ToString()), id); + + var reconverted = converter.ConvertTo(id, value.GetType()); + Assert.Equal(value, reconverted); + } + + [Fact] + public void CanCompareDefaults() + { + NullableStringId original = default; + var other = NullableStringId.Empty; + + var compare1 = original.CompareTo(other); + var compare2 = other.CompareTo(original); + Assert.Equal(compare1, -compare2); + } + + [Fact] + public void CanEquateDefaults() + { + NullableStringId original = default; + var other = NullableStringId.Empty; + + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); + + Assert.Equal(equals1, equals2); + } + + [Fact] + public void ImplementsInterfaces() + { + Assert.IsAssignableFrom>(NullableStringId.Empty); + Assert.IsAssignableFrom>(NullableStringId.Empty); + +#pragma warning disable 184 +#pragma warning disable CS0183 + Assert.True(NullableStringId.Empty is IComparable); + Assert.True(NullableStringId.Empty is IEquatable); +#pragma warning restore CS0183 +#pragma warning restore 184 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(NullableStringId.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs("123"); + ParseSpan("123".AsSpan()); + + T ParseAs(string s) where T : IParsable + { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + { + return T.Parse(s, null); + } +#endif + } + + [Fact] + public void NullValueIsNull() + { + var value = new NullableStringId(null); + Assert.Null(value.Value); + } + + [Fact] + public void CanEquateNullableValues() + { + var value1 = new NullableStringId(null); + var value2 = new NullableStringId(null); + var value3 = new NullableStringId(string.Empty); + + Assert.True(value1.Equals(value2)); + Assert.True(value1.Equals((object)value2)); + + Assert.False(value1.Equals(value3)); + Assert.False(value1.Equals((object)value3)); + Assert.False(value3.Equals((object)value1)); + } + + [Fact] + public void NullHashCodes() + { + var value1 = new NullableStringId(null); + var value2 = new NullableStringId(null); + var value3 = new NullableStringId("something"); + var value4 = new NullableStringId(string.Empty); + + Assert.Equal(value1.GetHashCode(), value2.GetHashCode()); + Assert.NotEqual(value1.GetHashCode(), value3.GetHashCode()); + Assert.NotEqual(value1.GetHashCode(), value4.GetHashCode()); + } + + [Fact] + public void NullSerializesAsExpectedWithConverters() + { + var expected = "null"; + var value = new ConvertersNullableStringId(null); + + var json = SystemTextJsonSerializer.Serialize(value); + var systemText = SystemTextJsonSerializer.Serialize(value); + Assert.Equal(expected, systemText); + Assert.Equal(expected, json); + } + + [Fact] + public void TypeConverterConvertsNullAsExpected() + { + var converter = TypeDescriptor.GetConverter(typeof(ConvertersNullableStringId)); + var id = converter.ConvertFrom(null); + Assert.IsType(id); + Assert.Equal(new ConvertersNullableStringId(null), id); + + var reconverted = converter.ConvertTo(id, typeof(string)); + Assert.Null(reconverted); + } + +#if NET6_0_OR_GREATER + [Fact] + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity { Id = Guid.NewGuid(), Name = new ConvertersNullableStringId("some name") }; + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add(original); + context.SaveChanges(); + } + + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); + Assert.Equal(original.Name, retrieved.Name); + } + } + + internal class ConventionsDbContext : DbContext + { + public DbSet Entities { get; set; } + + public ConventionsDbContext(DbContextOptions options) : base(options) + { + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + configurationBuilder + .Properties() + .HaveConversion(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); + } + } +#endif + + internal class TestDbContext : DbContext + { + public DbSet Entities { get; set; } + + public TestDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Name) + .HasConversion(new ConvertersNullableStringId.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); + } + } + + internal class TestEntity + { + public Guid Id { get; set; } + public ConvertersNullableStringId Name { get; set; } + } + + + internal class EntityWithNullableId + { + public ConvertersNullableStringId? Id { get; set; } + } + } +} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs index 7e1882365..80ea56fe2 100644 --- a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs @@ -230,12 +230,12 @@ public void ImplementsInterfaces() #pragma warning restore 184 #if NET6_0_OR_GREATER - Assert.IsAssignableFrom(IntId.Empty); + Assert.IsAssignableFrom(StringId.Empty); #endif #if NET7_0_OR_GREATER // doesn't compile if doesn't implement it - ParseAs("123"); - ParseSpan("123".AsSpan()); + ParseAs("123"); + ParseSpan("123".AsSpan()); T ParseAs(string s) where T : IParsable { From f676b31ca679a041fb9b6d5fb4e8663e3c9b9dbf Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 3 Nov 2023 21:42:13 +0000 Subject: [PATCH 07/47] Add NewId template --- .../Templates/guid-full.typedid | 2 +- .../Templates/newid-full.typedid | 251 +++++++ .../DapperTypeHandlers.cs | 2 +- .../Enums.cs | 8 +- .../MassTransitNewIdTests.cs | 674 ++++++++---------- 5 files changed, 570 insertions(+), 367 deletions(-) create mode 100644 src/StronglyTypedIds/Templates/newid-full.typedid diff --git a/src/StronglyTypedIds/Templates/guid-full.typedid b/src/StronglyTypedIds/Templates/guid-full.typedid index cd696822e..09ec51a6d 100644 --- a/src/StronglyTypedIds/Templates/guid-full.typedid +++ b/src/StronglyTypedIds/Templates/guid-full.typedid @@ -154,7 +154,7 @@ #else => new(global::System.Guid.Parse(input)); #endif - + #if NET7_0_OR_GREATER /// #endif diff --git a/src/StronglyTypedIds/Templates/newid-full.typedid b/src/StronglyTypedIds/Templates/newid-full.typedid new file mode 100644 index 000000000..c0ec8e4c4 --- /dev/null +++ b/src/StronglyTypedIds/Templates/newid-full.typedid @@ -0,0 +1,251 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::MassTransit.NewId Value { get; } + + public PLACEHOLDERID(global::MassTransit.NewId value) + { + Value = value; + } + + public static PLACEHOLDERID New() => new PLACEHOLDERID(global::MassTransit.NewId.Next()); + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(global::MassTransit.NewId.Empty); + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(System.Guid) || sourceType == typeof(global::MassTransit.NewId) + || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::MassTransit.NewId newIdValue => new PLACEHOLDERID(newIdValue), + global::System.Guid guidValue => new PLACEHOLDERID(global::MassTransit.NewId.FromGuid(guidValue)), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(global::MassTransit.NewId.FromGuid(result)), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(System.Guid) || sourceType == typeof(global::MassTransit.NewId) + || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(global::MassTransit.NewId)) + { + return idValue.Value; + } + + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value.ToGuid(); + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToGuid().ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(string) || typeToConvert == typeof(global::System.Guid) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (global::MassTransit.NewId.FromGuid(reader.GetGuid())); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value.ToGuid()); + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::MassTransit.NewId.FromGuid(reader.GetGuid())); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToGuid().ToString()); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input))); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input, provider))); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(global::MassTransit.NewId.FromGuid(guid)); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString(string? format, global::System.IFormatProvider? formatProvider) + => Value.ToGuid().ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input))); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input, provider))); +#else + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input))); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(global::MassTransit.NewId.FromGuid(guid)); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.ToGuid().TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.ToGuid().TryFormat(destination, out charsWritten, format); +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value.ToGuid(); + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + global::System.Guid guidValue => new PLACEHOLDERID(global::MassTransit.NewId.FromGuid(guidValue)), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(global::MassTransit.NewId.FromGuid(result)), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value.ToGuid(), + value => new PLACEHOLDERID(global::MassTransit.NewId.FromGuid(value)), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var guid = serializer.Deserialize(reader); + return guid.HasValue ? new PLACEHOLDERID(global::MassTransit.NewId.FromGuid(guid.Value)) : null; + } + } + } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs index 0a1e7cfa1..3c9f7b0c2 100644 --- a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs +++ b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs @@ -14,7 +14,7 @@ public static void AddHandlers() SqlMapper.AddTypeHandler(new ConvertersLongId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersStringId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersNullableStringId.DapperTypeHandler()); - // SqlMapper.AddTypeHandler(new DapperNewIdId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new NewIdId1.DapperTypeHandler()); } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index 9e4bc65c0..c54c9a3fb 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -30,12 +30,12 @@ partial struct LongId { } [StronglyTypedId("long-full")] partial struct ConvertersLongId { } - -[StronglyTypedId("newid")] + +[StronglyTypedId("newid-full")] partial struct NewIdId1 { } -[StronglyTypedId("newid")] -public partial struct NewIdId2 { } +[StronglyTypedId("newid-full")] +partial struct NewIdId2 { } [StronglyTypedId(Template.String)] partial struct StringId diff --git a/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs b/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs index 88d9292f0..6dac92cbd 100644 --- a/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs @@ -1,361 +1,313 @@ -// using System; -// using System.ComponentModel; -// using System.Linq; -// using System.Threading.Tasks; -// using Dapper; -// using MassTransit; -// using Microsoft.Data.Sqlite; -// using Microsoft.EntityFrameworkCore; -// using StronglyTypedIds.IntegrationTests.Types; -// using Xunit; -// using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; -// using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; -// -// namespace StronglyTypedIds.IntegrationTests -// { -// public class MassTransitNewIdTests -// { -// [Fact] -// public void SameValuesAreEqual() -// { -// var id = NewId.Next(); -// var foo1 = new NewIdId1(id); -// var foo2 = new NewIdId1(id); -// -// Assert.Equal(foo1, foo2); -// } -// -// [Fact] -// public void EmptyValueIsEmpty() -// { -// Assert.Equal(NewIdId1.Empty.Value, NewId.Empty); -// } -// -// -// [Fact] -// public void DifferentValuesAreUnequal() -// { -// var foo1 = NewIdId1.New(); -// var foo2 = NewIdId1.New(); -// -// Assert.NotEqual(foo1, foo2); -// } -// -// [Fact] -// public void OverloadsWorkCorrectly() -// { -// var id = NewId.Next(); -// var same1 = new NewIdId1(id); -// var same2 = new NewIdId1(id); -// var different = NewIdId1.New(); -// -// Assert.True(same1 == same2); -// Assert.False(same1 == different); -// Assert.False(same1 != same2); -// Assert.True(same1 != different); -// } -// -// [Fact] -// public void DifferentTypesAreUnequal() -// { -// var bar = NewIdId2.New(); -// var foo = NewIdId1.New(); -// -// //Assert.NotEqual(bar, foo); // does not compile -// Assert.NotEqual((object)bar, (object)foo); -// } -// -// [Fact] -// public void CantCreateEmptyGeneratedId1() -// { -// var foo = new NewIdId1(); -// var bar = new NewIdId2(); -// -// //Assert.NotEqual(bar, foo); // does not compile -// Assert.NotEqual((object)bar, (object)foo); -// } -// -// [Fact] -// public void CanSerializeToNewId_WithTypeConverter() -// { -// var foo = NewtonsoftJsonNewIdId.New(); -// -// var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedNewId = NewtonsoftJsonSerializer.SerializeObject(foo.Value.ToGuid()); -// -// Assert.Equal(serializedFoo, serializedNewId); -// } -// -// [Fact] -// public void CanSerializeToNewId_WithSystemTextJsonProvider() -// { -// var foo = SystemTextJsonNewIdId.New(); -// -// var serializedFoo = SystemTextJsonSerializer.Serialize(foo); -// var serializedNewId = SystemTextJsonSerializer.Serialize(foo.Value.ToGuid().ToString()); -// -// Assert.Equal(serializedFoo, serializedNewId); -// } -// -// [Fact] -// public void CanDeserializeFromNewId_WithNewtonsoftJsonProvider() -// { -// var value = NewId.Next(); -// var foo = new NewtonsoftJsonNewIdId(value); -// var serializedNewId = NewtonsoftJsonSerializer.SerializeObject(value.ToGuid()); -// -// var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedNewId); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() -// { -// var entity = new EntityWithNullableId { Id = null }; -// -// var json = NewtonsoftJsonSerializer.SerializeObject(entity); -// var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); -// -// Assert.NotNull(deserialize); -// Assert.Null(deserialize.Id); -// } -// -// [Fact] -// public void CanDeserializeFromNewId_WithSystemTextJsonProvider() -// { -// var value = NewId.Next(); -// var foo = new SystemTextJsonNewIdId(value); -// var serializedNewId = SystemTextJsonSerializer.Serialize(value.ToGuid()); -// -// var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedNewId); -// -// Assert.Equal(foo, deserializedFoo); -// } -// -// [Fact] -// public void CanSerializeToNewId_WithBothJsonConverters() -// { -// var foo = BothJsonNewIdId.New(); -// -// var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); -// var serializedNewId1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value.ToGuid().ToString()); -// -// var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); -// var serializedNewId2 = SystemTextJsonSerializer.Serialize(foo.Value.ToGuid().ToString()); -// -// Assert.Equal(serializedFoo1, serializedNewId1); -// Assert.Equal(serializedFoo2, serializedNewId2); -// } -// -// [Fact] -// public void WhenNoJsonConverter_SystemTextJsonSerializesWithValueProperty() -// { -// var foo = NoJsonNewIdId.New(); -// -// var serialized = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":" + SystemTextJsonSerializer.Serialize(foo.Value) + "}"; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() -// { -// var foo = NoJsonNewIdId.New(); -// -// var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); -// -// var expected = $"\"{foo.Value.ToGuid()}\""; -// -// Assert.Equal(expected, serialized); -// } -// -// [Fact] -// public void WhenNoTypeConverter_SerializesWithValueProperty() -// { -// var foo = NoConverterNewIdId.New(); -// -// var newtonsoft = SystemTextJsonSerializer.Serialize(foo); -// var systemText = SystemTextJsonSerializer.Serialize(foo); -// -// var expected = "{\"Value\":" + SystemTextJsonSerializer.Serialize(foo.Value) + "}"; -// -// Assert.Equal(expected, newtonsoft); -// Assert.Equal(expected, systemText); -// } -// -// [Fact] -// public void WhenEfCoreValueConverterUsesValueConverter() -// { -// var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// using (var context = new TestDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add( -// new TestEntity { Id = EfCoreNewIdId.New() }); -// context.SaveChanges(); -// } -// using (var context = new TestDbContext(options)) -// { -// var all = context.Entities.ToList(); -// Assert.Single(all); -// } -// } -// -// [Fact] -// public async Task WhenDapperValueConverterUsesValueConverter() -// { -// using var connection = new SqliteConnection("DataSource=:memory:"); -// await connection.OpenAsync(); -// -// var results = await connection.QueryAsync("SELECT '5640dad4-862a-4738-9e3c-c76dc227eb66'"); -// -// var value = Assert.Single(results); -// Assert.Equal(new DapperNewIdId(NewId.FromGuid(Guid.Parse("5640dad4-862a-4738-9e3c-c76dc227eb66"))), value); -// } -// -// [Theory] -// [InlineData("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")] -// public void TypeConverter_CanConvertToAndFrom(string value) -// { -// var converter = TypeDescriptor.GetConverter(typeof(NoJsonNewIdId)); -// var id = converter.ConvertFrom(value); -// Assert.IsType(id); -// Assert.Equal(new NoJsonNewIdId(NewId.FromGuid(Guid.Parse(value))), id); -// -// var reconverted = converter.ConvertTo(id, value.GetType()); -// Assert.Equal(value, reconverted); -// } -// -// [Fact] -// public void CanCompareDefaults() -// { -// ComparableNewIdId original = default; -// var other = ComparableNewIdId.Empty; -// -// var compare1 = original.CompareTo(other); -// var compare2 = other.CompareTo(original); -// Assert.Equal(compare1, -compare2); -// } -// -// [Fact] -// public void CanEquateDefaults() -// { -// EquatableNewIdId original = default; -// var other = EquatableNewIdId.Empty; -// -// var equals1 = (original as IEquatable).Equals(other); -// var equals2 = (other as IEquatable).Equals(original); -// -// Assert.Equal(equals1, equals2); -// } -// -// [Fact] -// public void ImplementsInterfaces() -// { -// Assert.IsAssignableFrom>(BothNewIdId.Empty); -// Assert.IsAssignableFrom>(BothNewIdId.Empty); -// -// Assert.IsAssignableFrom>(EquatableNewIdId.Empty); -// Assert.IsAssignableFrom>(ComparableNewIdId.Empty); -// -// #pragma warning disable 184 -// Assert.False(NewIdId1.Empty is IComparable); -// Assert.False(NewIdId1.Empty is IEquatable); -// #pragma warning restore 184 -// } -// -// -// #if NET6_0_OR_GREATER -// [Fact] -// public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() -// { -// var connection = new SqliteConnection("DataSource=:memory:"); -// connection.Open(); -// -// var options = new DbContextOptionsBuilder() -// .UseSqlite(connection) -// .Options; -// -// using (var context = new ConventionsDbContext(options)) -// { -// context.Database.EnsureCreated(); -// context.Entities.Add( -// new TestEntity { Id = EfCoreNewIdId.New() }); -// context.SaveChanges(); -// } -// using (var context = new ConventionsDbContext(options)) -// { -// var all = context.Entities.ToList(); -// Assert.Single(all); -// } -// } -// -// public class ConventionsDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public ConventionsDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) -// { -// configurationBuilder -// .Properties() -// .HaveConversion(); -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .ValueGeneratedNever(); -// }); -// } -// } -// #endif -// -// public class TestDbContext : DbContext -// { -// public DbSet Entities { get; set; } -// -// public TestDbContext(DbContextOptions options) : base(options) -// { -// } -// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// modelBuilder -// .Entity(builder => -// { -// builder -// .Property(x => x.Id) -// .HasConversion(new EfCoreNewIdId.EfCoreValueConverter()) -// .ValueGeneratedNever(); -// }); -// } -// } -// -// public class TestEntity -// { -// public EfCoreNewIdId Id { get; set; } -// } -// -// public class EntityWithNullableId -// { -// public NewtonsoftJsonNewIdId? Id { get; set; } -// } -// } -// } \ No newline at end of file +using System; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; +using Dapper; +using MassTransit; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using StronglyTypedIds.IntegrationTests.Types; +using Xunit; +using NewtonsoftJsonSerializer = Newtonsoft.Json.JsonConvert; +using SystemTextJsonSerializer = System.Text.Json.JsonSerializer; + +namespace StronglyTypedIds.IntegrationTests +{ + public class MassTransitNewIdTests + { + [Fact] + public void SameValuesAreEqual() + { + var id = NewId.Next(); + var foo1 = new NewIdId1(id); + var foo2 = new NewIdId1(id); + + Assert.Equal(foo1, foo2); + } + + [Fact] + public void EmptyValueIsEmpty() + { + Assert.Equal(NewIdId1.Empty.Value, NewId.Empty); + } + + + [Fact] + public void DifferentValuesAreUnequal() + { + var foo1 = NewIdId1.New(); + var foo2 = NewIdId1.New(); + + Assert.NotEqual(foo1, foo2); + } + + [Fact] + public void OverloadsWorkCorrectly() + { + var id = NewId.Next(); + var same1 = new NewIdId1(id); + var same2 = new NewIdId1(id); + var different = NewIdId1.New(); + + Assert.True(same1 == same2); + Assert.False(same1 == different); + Assert.False(same1 != same2); + Assert.True(same1 != different); + } + + [Fact] + public void DifferentTypesAreUnequal() + { + var bar = NewIdId2.New(); + var foo = NewIdId1.New(); + + //Assert.NotEqual(bar, foo); // does not compile + Assert.NotEqual((object)bar, (object)foo); + } + + [Fact] + public void CantCreateEmptyGeneratedId1() + { + var foo = new NewIdId1(); + var bar = new NewIdId2(); + + //Assert.NotEqual(bar, foo); // does not compile + Assert.NotEqual((object)bar, (object)foo); + } + + [Fact] + public void CanSerializeToNewId_WithSystemTextJsonProvider() + { + var foo = NewIdId1.New(); + + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedNewId = SystemTextJsonSerializer.Serialize(foo.Value.ToGuid().ToString()); + + Assert.Equal(serializedFoo, serializedNewId); + } + + [Fact] + public void CanDeserializeFromNewId_WithNewtonsoftJsonProvider() + { + var value = NewId.Next(); + var foo = new NewIdId1(value); + var serializedNewId = NewtonsoftJsonSerializer.SerializeObject(value.ToGuid()); + + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedNewId); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() + { + var entity = new EntityWithNullableId { Id = null }; + + var json = NewtonsoftJsonSerializer.SerializeObject(entity); + var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); + + Assert.NotNull(deserialize); + Assert.Null(deserialize.Id); + } + + [Fact] + public void CanDeserializeFromNewId_WithSystemTextJsonProvider() + { + var value = NewId.Next(); + var foo = new NewIdId1(value); + var serializedNewId = SystemTextJsonSerializer.Serialize(value.ToGuid()); + + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedNewId); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void WhenEfCoreValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new TestDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add( + new TestEntity { Id = NewIdId1.New() }); + context.SaveChanges(); + } + using (var context = new TestDbContext(options)) + { + var all = context.Entities.ToList(); + Assert.Single(all); + } + } + + [Fact] + public async Task WhenDapperValueConverterUsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + await connection.OpenAsync(); + + var results = await connection.QueryAsync("SELECT '5640dad4-862a-4738-9e3c-c76dc227eb66'"); + + var value = Assert.Single(results); + Assert.Equal(new NewIdId1(NewId.FromGuid(Guid.Parse("5640dad4-862a-4738-9e3c-c76dc227eb66"))), value); + } + + [Theory] + [InlineData("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")] + public void TypeConverter_CanConvertToAndFrom(string value) + { + var converter = TypeDescriptor.GetConverter(typeof(NewIdId1)); + var id = converter.ConvertFrom(value); + Assert.IsType(id); + Assert.Equal(new NewIdId1(NewId.FromGuid(Guid.Parse(value))), id); + + var reconverted = converter.ConvertTo(id, value.GetType()); + Assert.Equal(value, reconverted); + } + + [Fact] + public void CanCompareDefaults() + { + NewIdId1 original = default; + var other = NewIdId1.Empty; + + var compare1 = original.CompareTo(other); + var compare2 = other.CompareTo(original); + Assert.Equal(compare1, -compare2); + } + + [Fact] + public void CanEquateDefaults() + { + NewIdId1 original = default; + var other = NewIdId1.Empty; + + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); + + Assert.Equal(equals1, equals2); + } + + [Fact] + public void ImplementsInterfaces() + { + Assert.IsAssignableFrom>(NewIdId1.Empty); + Assert.IsAssignableFrom>(NewIdId1.Empty); + +#pragma warning disable CS0183 +#pragma warning disable 184 + Assert.True(NewIdId1.Empty is IComparable); + Assert.True(NewIdId1.Empty is IEquatable); +#pragma warning restore 184 +#pragma warning restore CS0183 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(NewIdId1.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs(Guid.NewGuid().ToString()); + ParseSpan(Guid.NewGuid().ToString().AsSpan()); + + T ParseAs(string s) where T: IParsable { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T: ISpanParsable { + return T.Parse(s, null); + } +#endif + } + + +#if NET6_0_OR_GREATER + [Fact] + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add( + new TestEntity { Id = NewIdId1.New() }); + context.SaveChanges(); + } + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + Assert.Single(all); + } + } + + internal class ConventionsDbContext : DbContext + { + public DbSet Entities { get; set; } + + public ConventionsDbContext(DbContextOptions options) : base(options) + { + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + configurationBuilder + .Properties() + .HaveConversion(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); + } + } +#endif + + internal class TestDbContext : DbContext + { + public DbSet Entities { get; set; } + + public TestDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .HasConversion(new NewIdId1.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); + } + } + + internal class TestEntity + { + public NewIdId1 Id { get; set; } + } + + internal class EntityWithNullableId + { + public NewIdId1? Id { get; set; } + } + } +} \ No newline at end of file From c308c5c82402d0343b90c024da54c59542bdd0ba Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 3 Nov 2023 21:50:38 +0000 Subject: [PATCH 08/47] Update snapshots --- ...nerateNonDefaultIdInNamespace.verified.txt | 12 +- ...singGlobalAttribute.DotNet7_0.received.txt | 521 ------------------ ...hTemplateUsingGlobalAttribute.verified.txt | 12 +- 3 files changed, 12 insertions(+), 533 deletions(-) delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.DotNet7_0.received.txt diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index 3b50d0609..52603cd86 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -440,9 +440,9 @@ namespace SomeNamespace return false; } - if (int.TryParse(input, provider, out var guid)) + if (int.TryParse(input, provider, out var value)) { - result = new(guid); + result = new(value); return true; } @@ -454,7 +454,7 @@ namespace SomeNamespace /// public string ToString( #if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)] #endif string? format, global::System.IFormatProvider? formatProvider) @@ -482,12 +482,12 @@ namespace SomeNamespace public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) { #if NET7_0_OR_GREATER - if (int.TryParse(input, provider, out var guid)) + if (int.TryParse(input, provider, out var value)) #else - if (int.TryParse(input, out var guid)) + if (int.TryParse(input, out var value)) #endif { - result = new(guid); + result = new(value); return true; } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.DotNet7_0.received.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.DotNet7_0.received.txt deleted file mode 100644 index d6f15d917..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.DotNet7_0.received.txt +++ /dev/null @@ -1,521 +0,0 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute - { - /// - /// Make the struct a strongly typed ID - /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute - { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int32, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId: global::System.IComparable, global::System.IEquatable, global::System.IFormattable -#if NET6_0_OR_GREATER - ,global::System.ISpanFormattable -#if NET7_0_OR_GREATER - ,global::System.IParsable, global::System.ISpanParsable -#endif -#endif - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index 97406b9e9..6ece5218a 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -438,9 +438,9 @@ namespace StronglyTypedIds return false; } - if (int.TryParse(input, provider, out var guid)) + if (int.TryParse(input, provider, out var value)) { - result = new(guid); + result = new(value); return true; } @@ -452,7 +452,7 @@ namespace StronglyTypedIds /// public string ToString( #if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)] #endif string? format, global::System.IFormatProvider? formatProvider) @@ -480,12 +480,12 @@ namespace StronglyTypedIds public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) { #if NET7_0_OR_GREATER - if (int.TryParse(input, provider, out var guid)) + if (int.TryParse(input, provider, out var value)) #else - if (int.TryParse(input, out var guid)) + if (int.TryParse(input, out var value)) #endif { - result = new(guid); + result = new(value); return true; } From f013f8f8bd171f6e8efb4084e831a749162bc190 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 4 Nov 2023 10:34:40 +0000 Subject: [PATCH 09/47] Lots of fixes --- src/StronglyTypedIds/EmbeddedSources.Guid.cs | 2 +- src/StronglyTypedIds/EmbeddedSources.Int.cs | 2 +- src/StronglyTypedIds/EmbeddedSources.Long.cs | 2 +- .../EmbeddedSources.String.cs | 2 +- src/StronglyTypedIds/Parser.cs | 11 ++++- .../Templates/guid-full.typedid | 2 +- .../Templates/int-full.typedid | 2 +- .../Templates/long-full.typedid | 2 +- .../Templates/newid-full.typedid | 2 +- .../Templates/string-full.typedid | 2 +- .../Enums.cs | 27 ++++++------ .../GuidIdTests.cs | 41 ++++++++++++++++++ .../IntIdTests.cs | 41 ++++++++++++++++++ .../LongIdTests.cs | 41 ++++++++++++++++++ .../MassTransitNewIdTests.cs | 42 +++++++++++++++++++ .../NestedIdTests.cs | 10 ++--- .../NullableStringIdTests.cs | 41 ++++++++++++++++++ .../StringIdTests.cs | 41 ++++++++++++++++++ ...ateDefaultIdInGlobalNamespace.verified.txt | 2 +- ...yNestedIdInFileScopeNamespace.verified.txt | 2 +- ...nerateIdInFileScopedNamespace.verified.txt | 2 +- ...ests.CanGenerateIdInNamespace.verified.txt | 2 +- ...nerateMultipleIdsWithSameName.verified.txt | 4 +- ...eNestedIdInFileScopeNamespace.verified.txt | 2 +- ...nerateNonDefaultIdInNamespace.verified.txt | 2 +- ...yNestedIdInFileScopeNamespace.verified.txt | 4 +- ...hTemplateUsingGlobalAttribute.verified.txt | 2 +- ...ttributesGeneratesWithDefault.verified.txt | 2 +- 28 files changed, 296 insertions(+), 41 deletions(-) diff --git a/src/StronglyTypedIds/EmbeddedSources.Guid.cs b/src/StronglyTypedIds/EmbeddedSources.Guid.cs index 9bd791ead..51fcd9b2c 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Guid.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Guid.cs @@ -94,7 +94,7 @@ public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACE #if NET6_0_OR_GREATER public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); diff --git a/src/StronglyTypedIds/EmbeddedSources.Int.cs b/src/StronglyTypedIds/EmbeddedSources.Int.cs index 8ec6e1bc3..59773ca62 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Int.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Int.cs @@ -93,7 +93,7 @@ public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACE #if NET6_0_OR_GREATER public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt32()); + => new(int.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); diff --git a/src/StronglyTypedIds/EmbeddedSources.Long.cs b/src/StronglyTypedIds/EmbeddedSources.Long.cs index 09e9271f0..83775e092 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Long.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Long.cs @@ -93,7 +93,7 @@ public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACE #if NET6_0_OR_GREATER public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt64()); + => new(long.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); diff --git a/src/StronglyTypedIds/EmbeddedSources.String.cs b/src/StronglyTypedIds/EmbeddedSources.String.cs index 74c0e3a53..b83bcd2b1 100644 --- a/src/StronglyTypedIds/EmbeddedSources.String.cs +++ b/src/StronglyTypedIds/EmbeddedSources.String.cs @@ -103,7 +103,7 @@ public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACE #if NET6_0_OR_GREATER public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetString()!); + => new(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null")); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value); diff --git a/src/StronglyTypedIds/Parser.cs b/src/StronglyTypedIds/Parser.cs index 3855f539a..e3bb5f6fd 100644 --- a/src/StronglyTypedIds/Parser.cs +++ b/src/StronglyTypedIds/Parser.cs @@ -243,9 +243,18 @@ potentialNamespaceParent is not NamespaceDeclarationSyntax while (parentIdClass != null && IsAllowedKind(parentIdClass.Kind())) { + var keyword = parentIdClass is RecordDeclarationSyntax record + ? record.ClassOrStructKeyword.Kind() switch + { + SyntaxKind.StructKeyword => "record struct", + SyntaxKind.ClassKeyword => "record class", + _ => "record", + } + : parentIdClass.Keyword.ValueText; + parentClass = new ParentClass( Modifiers: parentIdClass.Modifiers.ToString(), - Keyword: parentIdClass.Keyword.ValueText, + Keyword: keyword, Name: parentIdClass.Identifier.ToString() + parentIdClass.TypeParameterList, Constraints: parentIdClass.ConstraintClauses.ToString(), Child: parentClass, diff --git a/src/StronglyTypedIds/Templates/guid-full.typedid b/src/StronglyTypedIds/Templates/guid-full.typedid index 09ec51a6d..6feacc938 100644 --- a/src/StronglyTypedIds/Templates/guid-full.typedid +++ b/src/StronglyTypedIds/Templates/guid-full.typedid @@ -90,7 +90,7 @@ #if NET6_0_OR_GREATER public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); diff --git a/src/StronglyTypedIds/Templates/int-full.typedid b/src/StronglyTypedIds/Templates/int-full.typedid index f6abd5a6a..100d38f25 100644 --- a/src/StronglyTypedIds/Templates/int-full.typedid +++ b/src/StronglyTypedIds/Templates/int-full.typedid @@ -89,7 +89,7 @@ #if NET6_0_OR_GREATER public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt32()); + => new(int.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); diff --git a/src/StronglyTypedIds/Templates/long-full.typedid b/src/StronglyTypedIds/Templates/long-full.typedid index 5818fdd28..33e71cebc 100644 --- a/src/StronglyTypedIds/Templates/long-full.typedid +++ b/src/StronglyTypedIds/Templates/long-full.typedid @@ -89,7 +89,7 @@ #if NET6_0_OR_GREATER public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt32()); + => new(long.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); diff --git a/src/StronglyTypedIds/Templates/newid-full.typedid b/src/StronglyTypedIds/Templates/newid-full.typedid index c0ec8e4c4..76d6ca699 100644 --- a/src/StronglyTypedIds/Templates/newid-full.typedid +++ b/src/StronglyTypedIds/Templates/newid-full.typedid @@ -98,7 +98,7 @@ #if NET6_0_OR_GREATER public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::MassTransit.NewId.FromGuid(reader.GetGuid())); + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null")))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToGuid().ToString()); diff --git a/src/StronglyTypedIds/Templates/string-full.typedid b/src/StronglyTypedIds/Templates/string-full.typedid index ac6201e45..f04dbab67 100644 --- a/src/StronglyTypedIds/Templates/string-full.typedid +++ b/src/StronglyTypedIds/Templates/string-full.typedid @@ -99,7 +99,7 @@ #if NET6_0_OR_GREATER public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetString()!); + => new(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null")); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value); diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index c54c9a3fb..12d0d7525 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -66,18 +66,17 @@ partial struct NullableStringId { } [StronglyTypedId("nullablestring-full")] partial struct ConvertersNullableStringId { } +public partial class SomeType where T : new() +{ + public partial record struct NestedType + { + public partial struct MoreNesting + { + [StronglyTypedId] + public readonly partial struct VeryNestedId + { + } + } + } +} -// public partial class SomeType where T : new() -// { -// public partial record struct NestedType -// { -// public partial struct MoreNesting -// { -// [StronglyTypedId] -// public readonly partial struct VeryNestedIds -// { -// } -// } -// } -// } -// diff --git a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs index 605914e46..3b346d482 100644 --- a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Dapper; using Microsoft.Data.Sqlite; @@ -108,6 +110,40 @@ public void CanDeserializeFromGuid_WithSystemTextJsonProvider() Assert.Equal(foo, deserializedFoo); } +#if NET6_0_OR_GREATER + [Fact] + public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() + { + var value = new TypeWithDictionaryKeys() + { + Values = new() + }; + var guid = new GuidId1(Guid.Parse("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")); + value.Values.Add(guid, "My Value"); + var opts = new JsonSerializerOptions + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + var serialized = SystemTextJsonSerializer.Serialize(value, opts); + + var expected = $$""" + { + "values": { + "78104553-f1cd-41ec-bcb6-d3a8ff8d994d": "My Value" + } + } + """; + Assert.Equal(serialized, expected); + + var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); + + Assert.NotNull(deserialized.Values); + Assert.True(deserialized.Values.ContainsKey(guid)); + Assert.Equal("My Value", deserialized.Values[guid]); + } +#endif + [Fact] public void CanDeserializeFromGuid_WithNewtonsoftJsonProvider() { @@ -346,5 +382,10 @@ internal class EntityWithNullableId { public ConvertersGuidId? Id { get; set; } } + + internal class TypeWithDictionaryKeys + { + public Dictionary Values { get; set; } + } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs index 24ce6dcce..6da642457 100644 --- a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Dapper; using Microsoft.Data.Sqlite; @@ -98,6 +100,40 @@ public void CanSerializeToInt_WithSystemTextJsonProvider() Assert.Equal(serializedFoo, serializedInt); } +#if NET6_0_OR_GREATER + [Fact] + public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() + { + var value = new TypeWithDictionaryKeys() + { + Values = new() + }; + var key = new IntId(123); + value.Values.Add(key, "My Value"); + var opts = new JsonSerializerOptions + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + var serialized = SystemTextJsonSerializer.Serialize(value, opts); + + var expected = $$""" + { + "values": { + "123": "My Value" + } + } + """; + Assert.Equal(serialized, expected); + + var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); + + Assert.NotNull(deserialized.Values); + Assert.True(deserialized.Values.ContainsKey(key)); + Assert.Equal("My Value", deserialized.Values[key]); + } +#endif + [Fact] public void CanDeserializeFromInt_WithNewtonsoftJsonProvider() { @@ -327,4 +363,9 @@ internal class EntityWithNullableId { public ConvertersIntId? Id { get; set; } } + + internal class TypeWithDictionaryKeys + { + public Dictionary Values { get; set; } + } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs index 637bb5120..617e2d7df 100644 --- a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Dapper; using Microsoft.Data.Sqlite; @@ -98,6 +100,40 @@ public void CanSerializeToLong_WithSystemTextJsonProvider() Assert.Equal(serializedFoo, serializedLong); } +#if NET6_0_OR_GREATER + [Fact] + public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() + { + var value = new TypeWithDictionaryKeys() + { + Values = new() + }; + var key = new LongId(123); + value.Values.Add(key, "My Value"); + var opts = new JsonSerializerOptions + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + var serialized = SystemTextJsonSerializer.Serialize(value, opts); + + var expected = $$""" + { + "values": { + "123": "My Value" + } + } + """; + Assert.Equal(serialized, expected); + + var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); + + Assert.NotNull(deserialized.Values); + Assert.True(deserialized.Values.ContainsKey(key)); + Assert.Equal("My Value", deserialized.Values[key]); + } +#endif + [Fact] public void CanDeserializeFromLong_WithNewtonsoftJsonProvider() { @@ -326,5 +362,10 @@ internal class EntityWithNullableId { public ConvertersLongId? Id { get; set; } } + + internal class TypeWithDictionaryKeys + { + public Dictionary Values { get; set; } + } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs b/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs index 6dac92cbd..675ecad98 100644 --- a/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/MassTransitNewIdTests.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Dapper; using MassTransit; @@ -86,6 +88,41 @@ public void CanSerializeToNewId_WithSystemTextJsonProvider() Assert.Equal(serializedFoo, serializedNewId); } +#if NET6_0_OR_GREATER + [Fact] + public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() + { + var value = new TypeWithDictionaryKeys() + { + Values = new() + }; + + var key = new NewIdId1(NewId.FromGuid(Guid.Parse("78104553-f1cd-41ec-bcb6-d3a8ff8d994d"))); + value.Values.Add(key, "My Value"); + var opts = new JsonSerializerOptions + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + var serialized = SystemTextJsonSerializer.Serialize(value, opts); + + var expected = $$""" + { + "values": { + "78104553-f1cd-41ec-bcb6-d3a8ff8d994d": "My Value" + } + } + """; + Assert.Equal(serialized, expected); + + var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); + + Assert.NotNull(deserialized.Values); + Assert.True(deserialized.Values.ContainsKey(key)); + Assert.Equal("My Value", deserialized.Values[key]); + } +#endif + [Fact] public void CanDeserializeFromNewId_WithNewtonsoftJsonProvider() { @@ -309,5 +346,10 @@ internal class EntityWithNullableId { public NewIdId1? Id { get; set; } } + + internal class TypeWithDictionaryKeys + { + public Dictionary Values { get; set; } + } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/NestedIdTests.cs b/test/StronglyTypedIds.IntegrationTests/NestedIdTests.cs index 173417743..c58336747 100644 --- a/test/StronglyTypedIds.IntegrationTests/NestedIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/NestedIdTests.cs @@ -5,9 +5,9 @@ namespace StronglyTypedIds.IntegrationTests; public class NestedIdTests { - // [Fact] - // public void CanCreateNestedId() - // { - // var id = SomeType.NestedType.MoreNesting.VeryNestedId.New(); - // } + [Fact] + public void CanCreateNestedId() + { + var id = SomeType.NestedType.MoreNesting.VeryNestedId.New(); + } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs index d1666148c..58f943cb7 100644 --- a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Dapper; using Microsoft.Data.Sqlite; @@ -100,6 +102,40 @@ public void CanSerializeToString_WithSystemTextJsonProvider() Assert.Equal(serializedFoo, serializedString); } +#if NET6_0_OR_GREATER + [Fact] + public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() + { + var value = new TypeWithDictionaryKeys() + { + Values = new() + }; + + var key = new NullableStringId("78104553-f1cd-41ec-bcb6-d3a8ff8d994d"); + value.Values.Add(key, "My Value"); + var opts = new JsonSerializerOptions + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + var serialized = SystemTextJsonSerializer.Serialize(value, opts); + + var expected = $$""" + { + "values": { + "78104553-f1cd-41ec-bcb6-d3a8ff8d994d": "My Value" + } + } + """; + Assert.Equal(serialized, expected); + + var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); + + Assert.NotNull(deserialized.Values); + Assert.True(deserialized.Values.ContainsKey(key)); + Assert.Equal("My Value", deserialized.Values[key]); + } +#endif [Fact] public void CanDeserializeFromString_WithNewtonsoftJsonProvider() { @@ -392,5 +428,10 @@ internal class EntityWithNullableId { public ConvertersNullableStringId? Id { get; set; } } + + internal class TypeWithDictionaryKeys + { + public Dictionary Values { get; set; } + } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs index 80ea56fe2..c27b6ff8a 100644 --- a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Dapper; using Microsoft.Data.Sqlite; @@ -103,6 +105,40 @@ public void CanSerializeToString_WithSystemTextJsonProvider() Assert.Equal(serializedFoo, serializedString); } +#if NET6_0_OR_GREATER + [Fact] + public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() + { + var value = new TypeWithDictionaryKeys() + { + Values = new() + }; + + var key = new StringId("78104553-f1cd-41ec-bcb6-d3a8ff8d994d"); + value.Values.Add(key, "My Value"); + var opts = new JsonSerializerOptions + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + var serialized = SystemTextJsonSerializer.Serialize(value, opts); + + var expected = $$""" + { + "values": { + "78104553-f1cd-41ec-bcb6-d3a8ff8d994d": "My Value" + } + } + """; + Assert.Equal(serialized, expected); + + var deserialized = SystemTextJsonSerializer.Deserialize(serialized, opts); + + Assert.NotNull(deserialized.Values); + Assert.True(deserialized.Values.ContainsKey(key)); + Assert.Equal("My Value", deserialized.Values[key]); + } +#endif [Fact] public void CanDeserializeFromString_WithNewtonsoftJsonProvider() @@ -337,5 +373,10 @@ internal class EntityWithNullableId { public ConvertersStringId? Id { get; set; } } + + internal class TypeWithDictionaryKeys + { + public Dictionary Values { get; set; } + } } } \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index d0568badd..3ba3d6cfe 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -412,7 +412,7 @@ namespace StronglyTypedIds #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt index 58ec20237..8534c7a48 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -418,7 +418,7 @@ namespace SomeNamespace #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index d7ab88402..431f6b783 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -414,7 +414,7 @@ namespace SomeNamespace #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index d7ab88402..431f6b783 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -414,7 +414,7 @@ namespace SomeNamespace #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 6e46018a3..96e0c3bb3 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -414,7 +414,7 @@ namespace MyContracts.V1 #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); @@ -631,7 +631,7 @@ namespace MyContracts.V2 #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index 6197b7590..cf8d1f61d 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -416,7 +416,7 @@ namespace SomeNamespace #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index 52603cd86..5be631803 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -413,7 +413,7 @@ namespace SomeNamespace #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt32()); + => new(int.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index 7609f784c..f304ae8bd 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -325,7 +325,7 @@ namespace SomeNamespace { internal partial record InnerClass { - public readonly partial record InnerStruct + public readonly partial record struct InnerStruct { [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] @@ -420,7 +420,7 @@ namespace SomeNamespace #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index 6ece5218a..d794cbb13 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -411,7 +411,7 @@ namespace StronglyTypedIds #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetInt32()); + => new(int.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt index d0568badd..3ba3d6cfe 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt @@ -412,7 +412,7 @@ namespace StronglyTypedIds #if NET6_0_OR_GREATER public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString()!)); + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) => writer.WritePropertyName(value.Value.ToString()); From aee3728351a6dcdb25ee1672d7bb099b6cdb55aa Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 4 Nov 2023 11:48:06 +0000 Subject: [PATCH 10/47] Fix packaging (and remove other package) --- StronglyTypedId.sln | 15 ---- build/Build.cs | 2 +- .../StronglyTypedIds.Templates.csproj | 11 --- src/StronglyTypedIds.Templates/newid.typedid | 89 ------------------- .../StronglyTypedId.targets} | 0 src/StronglyTypedIds/StronglyTypedIds.csproj | 5 ++ ...s.Nuget.Attributes.IntegrationTests.csproj | 2 +- ...nglyTypedIds.Nuget.IntegrationTests.csproj | 2 +- .../StronglyTypedIds.Tests.csproj | 2 +- 9 files changed, 9 insertions(+), 119 deletions(-) delete mode 100644 src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj delete mode 100644 src/StronglyTypedIds.Templates/newid.typedid rename src/{StronglyTypedIds.Templates/StronglyTypedIds.Templates.targets => StronglyTypedIds/StronglyTypedId.targets} (100%) diff --git a/StronglyTypedId.sln b/StronglyTypedId.sln index 84545c38b..cd44309c6 100644 --- a/StronglyTypedId.sln +++ b/StronglyTypedId.sln @@ -32,8 +32,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Nuget.Inte EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Nuget.Attributes.IntegrationTests", "test\StronglyTypedIds.Nuget.Attributes.IntegrationTests\StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj", "{19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Templates", "src\StronglyTypedIds.Templates\StronglyTypedIds.Templates.csproj", "{E0561C0B-A51D-4399-94A3-F44BA375AF4D}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -106,18 +104,6 @@ Global {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}.Release|Any CPU.ActiveCfg = Release|Any CPU {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}.Release|x64.ActiveCfg = Release|Any CPU {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}.Release|x86.ActiveCfg = Release|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|x64.ActiveCfg = Debug|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|x64.Build.0 = Debug|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|x86.ActiveCfg = Debug|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Debug|x86.Build.0 = Debug|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|Any CPU.Build.0 = Release|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|x64.ActiveCfg = Release|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|x64.Build.0 = Release|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|x86.ActiveCfg = Release|Any CPU - {E0561C0B-A51D-4399-94A3-F44BA375AF4D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -129,7 +115,6 @@ Global {F25F6E67-E62A-4075-86CF-4C4EDD7E4883} = {EE1258BD-3422-4F55-B9CF-B4D6C95DAD68} {A7355210-7DDC-4968-84B7-79002113EA6E} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} - {E0561C0B-A51D-4399-94A3-F44BA375AF4D} = {EE1258BD-3422-4F55-B9CF-B4D6C95DAD68} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8D1F0534-B8AD-4CFA-9C14-CBC757BCB1E1} diff --git a/build/Build.cs b/build/Build.cs index 39bb2c919..aa78772cd 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -116,7 +116,7 @@ class Build : NukeBuild var projectFiles = new[] { TestsDirectory / "StronglyTypedIds.Nuget.IntegrationTests", - TestsDirectory / "StronglyTypedIds.Nuget.Attributes.IntegrationTests", + // TestsDirectory / "StronglyTypedIds.Nuget.Attributes.IntegrationTests", }; if (!string.IsNullOrEmpty(PackagesDirectory)) diff --git a/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj b/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj deleted file mode 100644 index bc9b36ab9..000000000 --- a/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - netstandard2.0;net461 - false - - - - - - diff --git a/src/StronglyTypedIds.Templates/newid.typedid b/src/StronglyTypedIds.Templates/newid.typedid deleted file mode 100644 index e87f9f725..000000000 --- a/src/StronglyTypedIds.Templates/newid.typedid +++ /dev/null @@ -1,89 +0,0 @@ - [System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] - readonly partial struct PLACEHOLDERID : INTERFACES - { - public MassTransit.NewId Value { get; } - - public PLACEHOLDERID(MassTransit.NewId value) - { - Value = value; - } - - public static PLACEHOLDERID New() => new PLACEHOLDERID(MassTransit.NewId.Next()); - public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(MassTransit.NewId.Empty); - - public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is PLACEHOLDERID other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); - public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - - public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - - class PLACEHOLDERIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || - sourceType == typeof(string) || base.CanConvertFrom - (context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - MassTransit.NewId newIdValue => new PLACEHOLDERID(newIdValue), - System.Guid guidValue => new PLACEHOLDERID(MassTransit.NewId.FromGuid(guidValue)), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(MassTransit.NewId.FromGuid(result)), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is PLACEHOLDERID idValue) - { - if (destinationType == typeof(MassTransit.NewId)) - { - return idValue.Value; - } - - if (destinationType == typeof(System.Guid)) - { - return idValue.Value.ToGuid(); - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToGuid().ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class PLACEHOLDERIDSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override PLACEHOLDERID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new PLACEHOLDERID(MassTransit.NewId.FromGuid(reader.GetGuid())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value.ToGuid()); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.targets b/src/StronglyTypedIds/StronglyTypedId.targets similarity index 100% rename from src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.targets rename to src/StronglyTypedIds/StronglyTypedId.targets diff --git a/src/StronglyTypedIds/StronglyTypedIds.csproj b/src/StronglyTypedIds/StronglyTypedIds.csproj index 95813be5f..ac155cec1 100644 --- a/src/StronglyTypedIds/StronglyTypedIds.csproj +++ b/src/StronglyTypedIds/StronglyTypedIds.csproj @@ -32,4 +32,9 @@ + + + + + \ No newline at end of file diff --git a/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj b/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj index 16fb810fc..f6eeea42e 100644 --- a/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj +++ b/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1;net6.0;net7.0 + netcoreapp3.1;net6.0;net7.0;net8.0 net48;$(TargetFrameworks) false STRONGLY_TYPED_ID_EMBED_ATTRIBUTES diff --git a/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj b/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj index 38b3c43f8..22322fa34 100644 --- a/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj +++ b/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1;net6.0;net7.0 + netcoreapp3.1;net6.0;net7.0;net8.0 net48;$(TargetFrameworks) false diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj index 6ee5e30ff..4ef5fe171 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj +++ b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1;net6.0;net7.0 + netcoreapp3.1;net6.0;net7.0;net8.0 net48;$(TargetFrameworks) false latest From 95d7b64107cb593583aae5d8e4184f9006d605e3 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 4 Nov 2023 12:54:54 +0000 Subject: [PATCH 11/47] Delete old files --- .../StronglyTypedIdAttribute.cs | 68 +-- .../StronglyTypedIdBackingType.cs | 22 - .../StronglyTypedIdConverter.cs | 50 -- .../StronglyTypedIdDefaultsAttribute.cs | 60 +-- .../StronglyTypedIdImplementations.cs | 37 -- src/StronglyTypedIds.Attributes/Template.cs | 15 +- src/StronglyTypedIds/EmbeddedSources.cs | 28 +- .../StronglyTypedIdGenerator.cs | 3 - .../Templates/Guid/Guid_Base.cs | 24 - .../Templates/Guid/Guid_DapperTypeHandler.cs | 18 - .../Guid/Guid_EfCoreValueConverter.cs | 11 - .../Templates/Guid/Guid_IComparable.cs | 1 - .../Guid/Guid_NewtonsoftJsonConverter.cs | 20 - .../Guid/Guid_SystemTextJsonConverter.cs | 13 - .../Templates/Guid/Guid_TypeConverter.cs | 41 -- .../Templates/Int/Int_Base.cs | 23 - .../Templates/Int/Int_DapperTypeHandler.cs | 19 - .../Templates/Int/Int_EfCoreValueConverter.cs | 11 - .../Templates/Int/Int_IComparable.cs | 1 - .../Int/Int_NewtonsoftJsonConverter.cs | 20 - .../Int/Int_SystemTextJsonConverter.cs | 13 - .../Templates/Int/Int_TypeConverter.cs | 41 -- .../Templates/Long/Long_Base.cs | 23 - .../Templates/Long/Long_DapperTypeHandler.cs | 20 - .../Long/Long_EfCoreValueConverter.cs | 11 - .../Templates/Long/Long_IComparable.cs | 1 - .../Long/Long_NewtonsoftJsonConverter.cs | 20 - .../Long/Long_SystemTextJsonConverter.cs | 13 - .../Templates/Long/Long_TypeConverter.cs | 43 -- .../Templates/NewId/NewId_Base.cs | 24 - .../NewId/NewId_DapperTypeHandler.cs | 18 - .../NewId/NewId_EfCoreValueConverter.cs | 11 - .../Templates/NewId/NewId_IComparable.cs | 1 - .../NewId/NewId_NewtonsoftJsonConverter.cs | 20 - .../NewId/NewId_SystemTextJsonConverter.cs | 13 - .../Templates/NewId/NewId_TypeConverter.cs | 49 -- .../NullableString/NullableString_Base.cs | 31 -- .../NullableString_DapperTypeHandler.cs | 19 - .../NullableString_EfCoreValueConverter.cs | 11 - .../NullableString_IComparable.cs | 10 - .../NullableString_NewtonsoftJsonConverter.cs | 26 - .../NullableString_SystemTextJsonConverter.cs | 20 - .../NullableString_TypeConverter.cs | 42 -- .../Templates/String/String_Base.cs | 32 -- .../String/String_DapperTypeHandler.cs | 17 - .../String/String_EfCoreValueConverter.cs | 11 - .../Templates/String/String_IComparable.cs | 10 - .../String/String_NewtonsoftJsonConverter.cs | 26 - .../String/String_SystemTextJsonConverter.cs | 13 - .../Templates/String/String_TypeConverter.cs | 37 -- .../EmbeddedResourceTests.cs | 5 +- ...urce=StronglyTypedIdAttribute.verified.txt | 58 +-- ...ce=StronglyTypedIdBackingType.verified.txt | 37 -- ...urce=StronglyTypedIdConverter.verified.txt | 65 --- ...onglyTypedIdDefaultsAttribute.verified.txt | 50 +- ...tronglyTypedIdImplementations.verified.txt | 52 -- ...ledResource_resource=Template.verified.txt | 1 + ...ateDefaultIdInGlobalNamespace.verified.txt | 257 ++-------- ....CanGenerateForCustomTemplate.verified.txt | 473 +++++++++--------- ...yNestedIdInFileScopeNamespace.verified.txt | 257 ++-------- ...nerateIdInFileScopedNamespace.verified.txt | 257 ++-------- ...ests.CanGenerateIdInNamespace.verified.txt | 257 ++-------- ...nerateMultipleIdsWithSameName.verified.txt | 257 ++-------- ...eNestedIdInFileScopeNamespace.verified.txt | 257 ++-------- ...nerateNonDefaultIdInNamespace.verified.txt | 257 ++-------- ...yNestedIdInFileScopeNamespace.verified.txt | 257 ++-------- ...eDefaultsUsingGlobalAttribute.verified.txt | 1 - ...mTemplateUsingGlobalAttribute.verified.txt | 473 +++++++++--------- ...hTemplateUsingGlobalAttribute.verified.txt | 257 ++-------- ...ttributesGeneratesWithDefault.verified.txt | 257 ++-------- .../StronglyTypedIdGeneratorTests.cs | 4 +- .../StronglyTypedIds.Tests.csproj | 2 +- 72 files changed, 1081 insertions(+), 3821 deletions(-) delete mode 100644 src/StronglyTypedIds.Attributes/StronglyTypedIdBackingType.cs delete mode 100644 src/StronglyTypedIds.Attributes/StronglyTypedIdConverter.cs delete mode 100644 src/StronglyTypedIds.Attributes/StronglyTypedIdImplementations.cs delete mode 100644 src/StronglyTypedIds/Templates/Guid/Guid_Base.cs delete mode 100644 src/StronglyTypedIds/Templates/Guid/Guid_DapperTypeHandler.cs delete mode 100644 src/StronglyTypedIds/Templates/Guid/Guid_EfCoreValueConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Guid/Guid_IComparable.cs delete mode 100644 src/StronglyTypedIds/Templates/Guid/Guid_NewtonsoftJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Guid/Guid_SystemTextJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Guid/Guid_TypeConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Int/Int_Base.cs delete mode 100644 src/StronglyTypedIds/Templates/Int/Int_DapperTypeHandler.cs delete mode 100644 src/StronglyTypedIds/Templates/Int/Int_EfCoreValueConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Int/Int_IComparable.cs delete mode 100644 src/StronglyTypedIds/Templates/Int/Int_NewtonsoftJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Int/Int_SystemTextJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Int/Int_TypeConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Long/Long_Base.cs delete mode 100644 src/StronglyTypedIds/Templates/Long/Long_DapperTypeHandler.cs delete mode 100644 src/StronglyTypedIds/Templates/Long/Long_EfCoreValueConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Long/Long_IComparable.cs delete mode 100644 src/StronglyTypedIds/Templates/Long/Long_NewtonsoftJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Long/Long_SystemTextJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/Long/Long_TypeConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/NewId/NewId_Base.cs delete mode 100644 src/StronglyTypedIds/Templates/NewId/NewId_DapperTypeHandler.cs delete mode 100644 src/StronglyTypedIds/Templates/NewId/NewId_EfCoreValueConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/NewId/NewId_IComparable.cs delete mode 100644 src/StronglyTypedIds/Templates/NewId/NewId_NewtonsoftJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/NewId/NewId_SystemTextJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/NewId/NewId_TypeConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/NullableString/NullableString_Base.cs delete mode 100644 src/StronglyTypedIds/Templates/NullableString/NullableString_DapperTypeHandler.cs delete mode 100644 src/StronglyTypedIds/Templates/NullableString/NullableString_EfCoreValueConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/NullableString/NullableString_IComparable.cs delete mode 100644 src/StronglyTypedIds/Templates/NullableString/NullableString_NewtonsoftJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/NullableString/NullableString_SystemTextJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/NullableString/NullableString_TypeConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/String/String_Base.cs delete mode 100644 src/StronglyTypedIds/Templates/String/String_DapperTypeHandler.cs delete mode 100644 src/StronglyTypedIds/Templates/String/String_EfCoreValueConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/String/String_IComparable.cs delete mode 100644 src/StronglyTypedIds/Templates/String/String_NewtonsoftJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/String/String_SystemTextJsonConverter.cs delete mode 100644 src/StronglyTypedIds/Templates/String/String_TypeConverter.cs delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdBackingType.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdConverter.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdImplementations.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt diff --git a/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs b/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs index cfb9b97bc..a8b1fe8ea 100644 --- a/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs +++ b/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs @@ -1,34 +1,32 @@ -using System; +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - public sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + public sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -43,15 +41,6 @@ public StronglyTypedIdAttribute(string templateName) TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -59,29 +48,14 @@ public StronglyTypedIdAttribute() { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } \ No newline at end of file diff --git a/src/StronglyTypedIds.Attributes/StronglyTypedIdBackingType.cs b/src/StronglyTypedIds.Attributes/StronglyTypedIdBackingType.cs deleted file mode 100644 index 0016511b6..000000000 --- a/src/StronglyTypedIds.Attributes/StronglyTypedIdBackingType.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - public enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} \ No newline at end of file diff --git a/src/StronglyTypedIds.Attributes/StronglyTypedIdConverter.cs b/src/StronglyTypedIds.Attributes/StronglyTypedIdConverter.cs deleted file mode 100644 index 599a51409..000000000 --- a/src/StronglyTypedIds.Attributes/StronglyTypedIdConverter.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - public enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} \ No newline at end of file diff --git a/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs b/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs index f7a7fb6a1..97ebf0c64 100644 --- a/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs +++ b/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs @@ -1,4 +1,15 @@ -using System; +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable namespace StronglyTypedIds { @@ -6,35 +17,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - public sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + public sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -51,29 +42,14 @@ public StronglyTypedIdDefaultsAttribute(string templateName) TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } \ No newline at end of file diff --git a/src/StronglyTypedIds.Attributes/StronglyTypedIdImplementations.cs b/src/StronglyTypedIds.Attributes/StronglyTypedIdImplementations.cs deleted file mode 100644 index d0900fc4f..000000000 --- a/src/StronglyTypedIds.Attributes/StronglyTypedIdImplementations.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - public enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} \ No newline at end of file diff --git a/src/StronglyTypedIds.Attributes/Template.cs b/src/StronglyTypedIds.Attributes/Template.cs index 1a2730191..6ec5e9473 100644 --- a/src/StronglyTypedIds.Attributes/Template.cs +++ b/src/StronglyTypedIds.Attributes/Template.cs @@ -1,4 +1,17 @@ -using System; +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +using System; namespace StronglyTypedIds { diff --git a/src/StronglyTypedIds/EmbeddedSources.cs b/src/StronglyTypedIds/EmbeddedSources.cs index eb26ffde1..41b940483 100644 --- a/src/StronglyTypedIds/EmbeddedSources.cs +++ b/src/StronglyTypedIds/EmbeddedSources.cs @@ -8,12 +8,9 @@ namespace StronglyTypedIds; internal static partial class EmbeddedSources { private static readonly Assembly ThisAssembly = typeof(EmbeddedSources).Assembly; - internal static readonly string StronglyTypedIdAttributeSource = LoadTemplateForEmitting("StronglyTypedIdAttribute"); - internal static readonly string StronglyTypedIdDefaultsAttributeSource = LoadTemplateForEmitting("StronglyTypedIdDefaultsAttribute"); - internal static readonly string StronglyTypedIdBackingTypeSource = LoadTemplateForEmitting("StronglyTypedIdBackingType"); - internal static readonly string StronglyTypedIdConverterSource = LoadTemplateForEmitting("StronglyTypedIdConverter"); - internal static readonly string StronglyTypedIdImplementationsSource = LoadTemplateForEmitting("StronglyTypedIdImplementations"); - internal static readonly string TemplateSource = LoadTemplateForEmitting("Template"); + internal static readonly string StronglyTypedIdAttributeSource = LoadAttributeTemplateForEmitting("StronglyTypedIdAttribute"); + internal static readonly string StronglyTypedIdDefaultsAttributeSource = LoadAttributeTemplateForEmitting("StronglyTypedIdDefaultsAttribute"); + internal static readonly string TemplateSource = LoadAttributeTemplateForEmitting("Template"); internal static readonly string AutoGeneratedHeader = LoadEmbeddedResource("StronglyTypedIds.Templates.AutoGeneratedHeader.cs"); @@ -42,15 +39,22 @@ internal static string LoadEmbeddedResource(string resourceName) return reader.ReadToEnd(); } - internal static string LoadTemplateForEmitting(string resourceName) + internal static string LoadAttributeTemplateForEmitting(string resourceName) { var resource = LoadEmbeddedResource($"StronglyTypedIds.Templates.Sources.{resourceName}.cs"); - return AutoGeneratedHeader + @"#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -" + resource + // AutoGeneratedHeader is included directly in the file + // so that it's there if you're directly referencing the attributes package too + return resource + .Replace("#nullable enable", """ + #nullable enable + + #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + """) .Replace("public sealed", "internal sealed") .Replace("public enum", "internal enum") - + @" -#endif"; + + """ + + #endif + """; } } \ No newline at end of file diff --git a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs index fc7ec707b..d142efd1f 100644 --- a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs +++ b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs @@ -23,9 +23,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { i.AddSource("StronglyTypedIdAttribute.g.cs", EmbeddedSources.StronglyTypedIdAttributeSource); i.AddSource("StronglyTypedIdDefaultsAttribute.g.cs", EmbeddedSources.StronglyTypedIdDefaultsAttributeSource); - i.AddSource("StronglyTypedIdBackingType.g.cs", EmbeddedSources.StronglyTypedIdBackingTypeSource); - i.AddSource("StronglyTypedIdConverter.g.cs", EmbeddedSources.StronglyTypedIdConverterSource); - i.AddSource("StronglyTypedIdImplementations.g.cs", EmbeddedSources.StronglyTypedIdImplementationsSource); i.AddSource("Template.g.cs", EmbeddedSources.TemplateSource); }); diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_Base.cs b/src/StronglyTypedIds/Templates/Guid/Guid_Base.cs deleted file mode 100644 index 200147a15..000000000 --- a/src/StronglyTypedIds/Templates/Guid/Guid_Base.cs +++ /dev/null @@ -1,24 +0,0 @@ - readonly partial struct TESTID : INTERFACES - { - public System.Guid Value { get; } - - public TESTID(System.Guid value) - { - Value = value; - } - - public static TESTID New() => new TESTID(System.Guid.NewGuid()); - public static readonly TESTID Empty = new TESTID(System.Guid.Empty); - - public bool Equals(TESTID other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is TESTID other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); - public static bool operator !=(TESTID a, TESTID b) => !(a == b); diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_DapperTypeHandler.cs b/src/StronglyTypedIds/Templates/Guid/Guid_DapperTypeHandler.cs deleted file mode 100644 index ef9fffd8c..000000000 --- a/src/StronglyTypedIds/Templates/Guid/Guid_DapperTypeHandler.cs +++ /dev/null @@ -1,18 +0,0 @@ - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, PLACEHOLDERID value) - { - parameter.Value = value.Value; - } - - public override PLACEHOLDERID Parse(object value) - { - return value switch - { - System.Guid guidValue => new PLACEHOLDERID(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), - }; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_EfCoreValueConverter.cs b/src/StronglyTypedIds/Templates/Guid/Guid_EfCoreValueConverter.cs deleted file mode 100644 index 7b046f3c5..000000000 --- a/src/StronglyTypedIds/Templates/Guid/Guid_EfCoreValueConverter.cs +++ /dev/null @@ -1,11 +0,0 @@ - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new PLACEHOLDERID(value), - mappingHints - ) { } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_IComparable.cs b/src/StronglyTypedIds/Templates/Guid/Guid_IComparable.cs deleted file mode 100644 index e0696ee2a..000000000 --- a/src/StronglyTypedIds/Templates/Guid/Guid_IComparable.cs +++ /dev/null @@ -1 +0,0 @@ - public int CompareTo(TESTID other) => Value.CompareTo(other.Value); \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_NewtonsoftJsonConverter.cs b/src/StronglyTypedIds/Templates/Guid/Guid_NewtonsoftJsonConverter.cs deleted file mode 100644 index 7e5c6446c..000000000 --- a/src/StronglyTypedIds/Templates/Guid/Guid_NewtonsoftJsonConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ - - class PLACEHOLDERIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(PLACEHOLDERID); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (PLACEHOLDERID)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new PLACEHOLDERID(guid.Value) : null; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_SystemTextJsonConverter.cs b/src/StronglyTypedIds/Templates/Guid/Guid_SystemTextJsonConverter.cs deleted file mode 100644 index 4dc733db9..000000000 --- a/src/StronglyTypedIds/Templates/Guid/Guid_SystemTextJsonConverter.cs +++ /dev/null @@ -1,13 +0,0 @@ - - class TESTIDSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override TESTID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new TESTID(System.Guid.Parse(reader.GetString())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, TESTID value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Guid/Guid_TypeConverter.cs b/src/StronglyTypedIds/Templates/Guid/Guid_TypeConverter.cs deleted file mode 100644 index 6ae7eb06b..000000000 --- a/src/StronglyTypedIds/Templates/Guid/Guid_TypeConverter.cs +++ /dev/null @@ -1,41 +0,0 @@ - - class TESTIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - System.Guid guidValue => new TESTID(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new TESTID(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is TESTID idValue) - { - if (destinationType == typeof(System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Int/Int_Base.cs b/src/StronglyTypedIds/Templates/Int/Int_Base.cs deleted file mode 100644 index 08ce1fca6..000000000 --- a/src/StronglyTypedIds/Templates/Int/Int_Base.cs +++ /dev/null @@ -1,23 +0,0 @@ - readonly partial struct TESTID : INTERFACES - { - public int Value { get; } - - public TESTID(int value) - { - Value = value; - } - - public static readonly TESTID Empty = new TESTID(0); - - public bool Equals(TESTID other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is TESTID other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); - public static bool operator !=(TESTID a, TESTID b) => !(a == b); diff --git a/src/StronglyTypedIds/Templates/Int/Int_DapperTypeHandler.cs b/src/StronglyTypedIds/Templates/Int/Int_DapperTypeHandler.cs deleted file mode 100644 index b67809c70..000000000 --- a/src/StronglyTypedIds/Templates/Int/Int_DapperTypeHandler.cs +++ /dev/null @@ -1,19 +0,0 @@ - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, PLACEHOLDERID value) - { - parameter.Value = value.Value; - } - - public override PLACEHOLDERID Parse(object value) - { - return value switch - { - int intValue => new PLACEHOLDERID(intValue), - long longValue when longValue < int.MaxValue => new PLACEHOLDERID((int)longValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), - }; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Int/Int_EfCoreValueConverter.cs b/src/StronglyTypedIds/Templates/Int/Int_EfCoreValueConverter.cs deleted file mode 100644 index 0378d4d52..000000000 --- a/src/StronglyTypedIds/Templates/Int/Int_EfCoreValueConverter.cs +++ /dev/null @@ -1,11 +0,0 @@ - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new PLACEHOLDERID(value), - mappingHints - ) { } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Int/Int_IComparable.cs b/src/StronglyTypedIds/Templates/Int/Int_IComparable.cs deleted file mode 100644 index e0696ee2a..000000000 --- a/src/StronglyTypedIds/Templates/Int/Int_IComparable.cs +++ /dev/null @@ -1 +0,0 @@ - public int CompareTo(TESTID other) => Value.CompareTo(other.Value); \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Int/Int_NewtonsoftJsonConverter.cs b/src/StronglyTypedIds/Templates/Int/Int_NewtonsoftJsonConverter.cs deleted file mode 100644 index b535cacfe..000000000 --- a/src/StronglyTypedIds/Templates/Int/Int_NewtonsoftJsonConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ - - class PLACEHOLDERIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(PLACEHOLDERID); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (PLACEHOLDERID)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var result = serializer.Deserialize(reader); - return result.HasValue ? new PLACEHOLDERID(result.Value) : null; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Int/Int_SystemTextJsonConverter.cs b/src/StronglyTypedIds/Templates/Int/Int_SystemTextJsonConverter.cs deleted file mode 100644 index e388d1e8e..000000000 --- a/src/StronglyTypedIds/Templates/Int/Int_SystemTextJsonConverter.cs +++ /dev/null @@ -1,13 +0,0 @@ - - class TESTIDSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override TESTID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new TESTID(reader.GetInt32()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, TESTID value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteNumberValue(value.Value); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Int/Int_TypeConverter.cs b/src/StronglyTypedIds/Templates/Int/Int_TypeConverter.cs deleted file mode 100644 index 23cc26327..000000000 --- a/src/StronglyTypedIds/Templates/Int/Int_TypeConverter.cs +++ /dev/null @@ -1,41 +0,0 @@ - - class TESTIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - int intValue => new TESTID(intValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new TESTID(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is TESTID idValue) - { - if (destinationType == typeof(int)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Long/Long_Base.cs b/src/StronglyTypedIds/Templates/Long/Long_Base.cs deleted file mode 100644 index 38d9fc5a6..000000000 --- a/src/StronglyTypedIds/Templates/Long/Long_Base.cs +++ /dev/null @@ -1,23 +0,0 @@ - readonly partial struct TESTID : INTERFACES - { - public long Value { get; } - - public TESTID(long value) - { - Value = value; - } - - public static readonly TESTID Empty = new TESTID(0); - - public bool Equals(TESTID other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is TESTID other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); - public static bool operator !=(TESTID a, TESTID b) => !(a == b); diff --git a/src/StronglyTypedIds/Templates/Long/Long_DapperTypeHandler.cs b/src/StronglyTypedIds/Templates/Long/Long_DapperTypeHandler.cs deleted file mode 100644 index 42dac85c9..000000000 --- a/src/StronglyTypedIds/Templates/Long/Long_DapperTypeHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, TESTID value) - { - parameter.Value = value.Value; - } - - public override TESTID Parse(object value) - { - return value switch - { - long longValue => new TESTID(longValue), - int intValue => new TESTID(intValue), - short shortValue => new TESTID(shortValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new TESTID(result), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to TESTID"), - }; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Long/Long_EfCoreValueConverter.cs b/src/StronglyTypedIds/Templates/Long/Long_EfCoreValueConverter.cs deleted file mode 100644 index 96422f377..000000000 --- a/src/StronglyTypedIds/Templates/Long/Long_EfCoreValueConverter.cs +++ /dev/null @@ -1,11 +0,0 @@ - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new TESTID(value), - mappingHints - ) { } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Long/Long_IComparable.cs b/src/StronglyTypedIds/Templates/Long/Long_IComparable.cs deleted file mode 100644 index e0696ee2a..000000000 --- a/src/StronglyTypedIds/Templates/Long/Long_IComparable.cs +++ /dev/null @@ -1 +0,0 @@ - public int CompareTo(TESTID other) => Value.CompareTo(other.Value); \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Long/Long_NewtonsoftJsonConverter.cs b/src/StronglyTypedIds/Templates/Long/Long_NewtonsoftJsonConverter.cs deleted file mode 100644 index f1bcb6a98..000000000 --- a/src/StronglyTypedIds/Templates/Long/Long_NewtonsoftJsonConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ - - class TESTIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(TESTID); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (TESTID)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var result = serializer.Deserialize(reader); - return result.HasValue ? new TESTID(result.Value) : null; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Long/Long_SystemTextJsonConverter.cs b/src/StronglyTypedIds/Templates/Long/Long_SystemTextJsonConverter.cs deleted file mode 100644 index 5cf5825eb..000000000 --- a/src/StronglyTypedIds/Templates/Long/Long_SystemTextJsonConverter.cs +++ /dev/null @@ -1,13 +0,0 @@ - - class TESTIDSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override TESTID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new TESTID(reader.GetInt64()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, TESTID value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteNumberValue(value.Value); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/Long/Long_TypeConverter.cs b/src/StronglyTypedIds/Templates/Long/Long_TypeConverter.cs deleted file mode 100644 index 4785b648f..000000000 --- a/src/StronglyTypedIds/Templates/Long/Long_TypeConverter.cs +++ /dev/null @@ -1,43 +0,0 @@ - - class TESTIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(long) || sourceType == typeof(int) || sourceType == typeof(short) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - long longValue => new TESTID(longValue), - int intValue => new TESTID(intValue), - short shortValue => new TESTID(shortValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new TESTID(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is TESTID idValue) - { - if (destinationType == typeof(long)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NewId/NewId_Base.cs b/src/StronglyTypedIds/Templates/NewId/NewId_Base.cs deleted file mode 100644 index 854cd477a..000000000 --- a/src/StronglyTypedIds/Templates/NewId/NewId_Base.cs +++ /dev/null @@ -1,24 +0,0 @@ - readonly partial struct TESTID : INTERFACES - { - public MassTransit.NewId Value { get; } - - public TESTID(MassTransit.NewId value) - { - Value = value; - } - - public static TESTID New() => new TESTID(MassTransit.NewId.Next()); - public static readonly TESTID Empty = new TESTID(MassTransit.NewId.Empty); - - public bool Equals(TESTID other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is TESTID other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); - public static bool operator !=(TESTID a, TESTID b) => !(a == b); diff --git a/src/StronglyTypedIds/Templates/NewId/NewId_DapperTypeHandler.cs b/src/StronglyTypedIds/Templates/NewId/NewId_DapperTypeHandler.cs deleted file mode 100644 index 8d4af7b02..000000000 --- a/src/StronglyTypedIds/Templates/NewId/NewId_DapperTypeHandler.cs +++ /dev/null @@ -1,18 +0,0 @@ - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, TESTID value) - { - parameter.Value = value.Value.ToGuid(); - } - - public override TESTID Parse(object value) - { - return value switch - { - System.Guid guidValue => new TESTID(MassTransit.NewId.FromGuid(guidValue)), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new TESTID(MassTransit.NewId.FromGuid(result)), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to TESTID"), - }; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NewId/NewId_EfCoreValueConverter.cs b/src/StronglyTypedIds/Templates/NewId/NewId_EfCoreValueConverter.cs deleted file mode 100644 index 6b838a340..000000000 --- a/src/StronglyTypedIds/Templates/NewId/NewId_EfCoreValueConverter.cs +++ /dev/null @@ -1,11 +0,0 @@ - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value.ToGuid(), - value => new TESTID(MassTransit.NewId.FromGuid(value)), - mappingHints - ) { } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NewId/NewId_IComparable.cs b/src/StronglyTypedIds/Templates/NewId/NewId_IComparable.cs deleted file mode 100644 index e0696ee2a..000000000 --- a/src/StronglyTypedIds/Templates/NewId/NewId_IComparable.cs +++ /dev/null @@ -1 +0,0 @@ - public int CompareTo(TESTID other) => Value.CompareTo(other.Value); \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NewId/NewId_NewtonsoftJsonConverter.cs b/src/StronglyTypedIds/Templates/NewId/NewId_NewtonsoftJsonConverter.cs deleted file mode 100644 index f3e02dafc..000000000 --- a/src/StronglyTypedIds/Templates/NewId/NewId_NewtonsoftJsonConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ - - class TESTIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(TESTID); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (TESTID)value; - serializer.Serialize(writer, id.Value.ToGuid()); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - var guid = serializer.Deserialize(reader); - return guid.HasValue ? new TESTID(MassTransit.NewId.FromGuid(guid.Value)) : null; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NewId/NewId_SystemTextJsonConverter.cs b/src/StronglyTypedIds/Templates/NewId/NewId_SystemTextJsonConverter.cs deleted file mode 100644 index 082fef2ba..000000000 --- a/src/StronglyTypedIds/Templates/NewId/NewId_SystemTextJsonConverter.cs +++ /dev/null @@ -1,13 +0,0 @@ - - class TESTIDSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override TESTID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new TESTID(MassTransit.NewId.FromGuid(reader.GetGuid())); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, TESTID value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value.ToGuid()); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NewId/NewId_TypeConverter.cs b/src/StronglyTypedIds/Templates/NewId/NewId_TypeConverter.cs deleted file mode 100644 index f923c90ab..000000000 --- a/src/StronglyTypedIds/Templates/NewId/NewId_TypeConverter.cs +++ /dev/null @@ -1,49 +0,0 @@ - - class TESTIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || - sourceType == typeof(string) || base.CanConvertFrom - (context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - return value switch - { - MassTransit.NewId newIdValue => new TESTID(newIdValue), - System.Guid guidValue => new TESTID(MassTransit.NewId.FromGuid(guidValue)), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new TESTID(MassTransit.NewId.FromGuid(result)), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is TESTID idValue) - { - if (destinationType == typeof(MassTransit.NewId)) - { - return idValue.Value; - } - - if (destinationType == typeof(System.Guid)) - { - return idValue.Value.ToGuid(); - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToGuid().ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NullableString/NullableString_Base.cs b/src/StronglyTypedIds/Templates/NullableString/NullableString_Base.cs deleted file mode 100644 index 94a6eaffb..000000000 --- a/src/StronglyTypedIds/Templates/NullableString/NullableString_Base.cs +++ /dev/null @@ -1,31 +0,0 @@ - readonly partial struct TESTID : INTERFACES - { - public string? Value { get; } - - public TESTID(string? value) - { - Value = value; - } - - public static readonly TESTID Empty = new TESTID(string.Empty); - - public bool Equals(TESTID other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is TESTID other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - public override string? ToString() => Value; - public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); - public static bool operator !=(TESTID a, TESTID b) => !(a == b); diff --git a/src/StronglyTypedIds/Templates/NullableString/NullableString_DapperTypeHandler.cs b/src/StronglyTypedIds/Templates/NullableString/NullableString_DapperTypeHandler.cs deleted file mode 100644 index 1524a13b1..000000000 --- a/src/StronglyTypedIds/Templates/NullableString/NullableString_DapperTypeHandler.cs +++ /dev/null @@ -1,19 +0,0 @@ - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, TESTID value) - { - parameter.Value = value.Value; - } - - public override TESTID Parse(object value) - { - return value switch - { - null => new TESTID(null), - System.DBNull => new TESTID(null), - string stringValue => new TESTID(stringValue), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to TESTID"), - }; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NullableString/NullableString_EfCoreValueConverter.cs b/src/StronglyTypedIds/Templates/NullableString/NullableString_EfCoreValueConverter.cs deleted file mode 100644 index 443ad1aa0..000000000 --- a/src/StronglyTypedIds/Templates/NullableString/NullableString_EfCoreValueConverter.cs +++ /dev/null @@ -1,11 +0,0 @@ - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) - : base( - id => id.Value!, - value => new TESTID(value), - mappingHints - ) { } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NullableString/NullableString_IComparable.cs b/src/StronglyTypedIds/Templates/NullableString/NullableString_IComparable.cs deleted file mode 100644 index 5cdc51ac9..000000000 --- a/src/StronglyTypedIds/Templates/NullableString/NullableString_IComparable.cs +++ /dev/null @@ -1,10 +0,0 @@ - public int CompareTo(TESTID other) - { - return (Value, other.Value) switch - { - (null, null) => 0, - (null, _) => -1, - (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), - }; - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NullableString/NullableString_NewtonsoftJsonConverter.cs b/src/StronglyTypedIds/Templates/NullableString/NullableString_NewtonsoftJsonConverter.cs deleted file mode 100644 index 9d536aa49..000000000 --- a/src/StronglyTypedIds/Templates/NullableString/NullableString_NewtonsoftJsonConverter.cs +++ /dev/null @@ -1,26 +0,0 @@ - - class TESTIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(TESTID); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object? value, Newtonsoft.Json.JsonSerializer serializer) - { - if (value is null) - { - serializer.Serialize(writer, null); - } - else - { - var id = (TESTID)value; - serializer.Serialize(writer, id.Value); - } - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - return new TESTID(serializer.Deserialize(reader)); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NullableString/NullableString_SystemTextJsonConverter.cs b/src/StronglyTypedIds/Templates/NullableString/NullableString_SystemTextJsonConverter.cs deleted file mode 100644 index 9f2f7cf1e..000000000 --- a/src/StronglyTypedIds/Templates/NullableString/NullableString_SystemTextJsonConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ - - class TESTIDSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override TESTID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new TESTID(reader.GetString()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, TESTID value, System.Text.Json.JsonSerializerOptions options) - { - if (value.Value is null) - { - writer.WriteNullValue(); - } - else - { - writer.WriteStringValue(value.Value); - } - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/NullableString/NullableString_TypeConverter.cs b/src/StronglyTypedIds/Templates/NullableString/NullableString_TypeConverter.cs deleted file mode 100644 index b0f90cc19..000000000 --- a/src/StronglyTypedIds/Templates/NullableString/NullableString_TypeConverter.cs +++ /dev/null @@ -1,42 +0,0 @@ - - class TESTIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) - { - if (value is null) - { - return new TESTID(null); - } - - var stringValue = value as string; - if (stringValue is not null) - { - return new TESTID(stringValue); - } - - return base.ConvertFrom(context, culture, value); - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Type? sourceType) - { - return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType) - { - if (value is TESTID idValue) - { - if (destinationType == typeof(string)) - { - return idValue.Value; - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/String/String_Base.cs b/src/StronglyTypedIds/Templates/String/String_Base.cs deleted file mode 100644 index 023df780b..000000000 --- a/src/StronglyTypedIds/Templates/String/String_Base.cs +++ /dev/null @@ -1,32 +0,0 @@ - readonly partial struct TESTID : INTERFACES - { - public string Value { get; } - - public TESTID(string value) - { - Value = value ?? throw new System.ArgumentNullException(nameof(value)); - } - - public static readonly TESTID Empty = new TESTID(string.Empty); - - public bool Equals(TESTID other) - { - return (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is TESTID other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value; - public static bool operator ==(TESTID a, TESTID b) => a.Equals(b); - public static bool operator !=(TESTID a, TESTID b) => !(a == b); diff --git a/src/StronglyTypedIds/Templates/String/String_DapperTypeHandler.cs b/src/StronglyTypedIds/Templates/String/String_DapperTypeHandler.cs deleted file mode 100644 index 93d6ff7bf..000000000 --- a/src/StronglyTypedIds/Templates/String/String_DapperTypeHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ - - public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler - { - public override void SetValue(System.Data.IDbDataParameter parameter, TESTID value) - { - parameter.Value = value.Value; - } - - public override TESTID Parse(object value) - { - return value switch - { - string stringValue => new TESTID(stringValue), - _ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to TESTID"), - }; - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/String/String_EfCoreValueConverter.cs b/src/StronglyTypedIds/Templates/String/String_EfCoreValueConverter.cs deleted file mode 100644 index 76a2b7a63..000000000 --- a/src/StronglyTypedIds/Templates/String/String_EfCoreValueConverter.cs +++ /dev/null @@ -1,11 +0,0 @@ - - public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter - { - public EfCoreValueConverter() : this(null) { } - public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null) - : base( - id => id.Value, - value => new TESTID(value), - mappingHints - ) { } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/String/String_IComparable.cs b/src/StronglyTypedIds/Templates/String/String_IComparable.cs deleted file mode 100644 index 5cdc51ac9..000000000 --- a/src/StronglyTypedIds/Templates/String/String_IComparable.cs +++ /dev/null @@ -1,10 +0,0 @@ - public int CompareTo(TESTID other) - { - return (Value, other.Value) switch - { - (null, null) => 0, - (null, _) => -1, - (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), - }; - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/String/String_NewtonsoftJsonConverter.cs b/src/StronglyTypedIds/Templates/String/String_NewtonsoftJsonConverter.cs deleted file mode 100644 index e331c4bdc..000000000 --- a/src/StronglyTypedIds/Templates/String/String_NewtonsoftJsonConverter.cs +++ /dev/null @@ -1,26 +0,0 @@ - - class TESTIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter - { - public override bool CanConvert(System.Type objectType) - { - return objectType == typeof(TESTID); - } - - public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) - { - var id = (TESTID)value; - serializer.Serialize(writer, id.Value); - } - - public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) - { - if (objectType == typeof(TESTID?)) - { - var value = serializer.Deserialize(reader); - - return value is null ? null : new TESTID(value); - } - - return new TESTID(serializer.Deserialize(reader)); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/String/String_SystemTextJsonConverter.cs b/src/StronglyTypedIds/Templates/String/String_SystemTextJsonConverter.cs deleted file mode 100644 index f5cf488e2..000000000 --- a/src/StronglyTypedIds/Templates/String/String_SystemTextJsonConverter.cs +++ /dev/null @@ -1,13 +0,0 @@ - - class TESTIDSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter - { - public override TESTID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) - { - return new TESTID(reader.GetString()); - } - - public override void Write(System.Text.Json.Utf8JsonWriter writer, TESTID value, System.Text.Json.JsonSerializerOptions options) - { - writer.WriteStringValue(value.Value); - } - } \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/String/String_TypeConverter.cs b/src/StronglyTypedIds/Templates/String/String_TypeConverter.cs deleted file mode 100644 index 52e9c128f..000000000 --- a/src/StronglyTypedIds/Templates/String/String_TypeConverter.cs +++ /dev/null @@ -1,37 +0,0 @@ - - class TESTIDTypeConverter : System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - var stringValue = value as string; - if (stringValue is not null) - { - return new TESTID(stringValue); - } - - return base.ConvertFrom(context, culture, value); - } - - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) - { - if (value is TESTID idValue) - { - if (destinationType == typeof(string)) - { - return idValue.Value; - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/EmbeddedResourceTests.cs b/test/StronglyTypedIds.Tests/EmbeddedResourceTests.cs index 412c6c8ab..fd4aef693 100644 --- a/test/StronglyTypedIds.Tests/EmbeddedResourceTests.cs +++ b/test/StronglyTypedIds.Tests/EmbeddedResourceTests.cs @@ -11,9 +11,6 @@ public class EmbeddedResourceTests { "StronglyTypedIdAttribute", "StronglyTypedIdDefaultsAttribute", - "StronglyTypedIdBackingType", - "StronglyTypedIdConverter", - "StronglyTypedIdImplementations", "Template", }; @@ -21,7 +18,7 @@ public class EmbeddedResourceTests [MemberData(nameof(EmbeddedResources))] public Task EmittedResourceIsSameAsCompiledResource(string resource) { - var embedded = EmbeddedSources.LoadTemplateForEmitting(resource); + var embedded = EmbeddedSources.LoadAttributeTemplateForEmitting(resource); return Verifier.Verify(embedded) .UseDirectory("Snapshots") diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt index 1407dd75d..ffe2528a8 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt @@ -10,39 +10,25 @@ #pragma warning disable 1591 // publicly visible type or member must be documented #nullable enable -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES -using System; +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -57,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -73,30 +50,15 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdBackingType.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdBackingType.verified.txt deleted file mode 100644 index 921a10fce..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdBackingType.verified.txt +++ /dev/null @@ -1,37 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdConverter.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdConverter.verified.txt deleted file mode 100644 index d3f7ebf63..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdConverter.verified.txt +++ /dev/null @@ -1,65 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, - } -} -#endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt index 35133ef98..cd82ba82f 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt @@ -10,9 +10,8 @@ #pragma warning disable 1591 // publicly visible type or member must be documented #nullable enable -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES -using System; +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -20,35 +19,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -65,30 +44,15 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdImplementations.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdImplementations.verified.txt deleted file mode 100644 index 92b322504..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdImplementations.verified.txt +++ /dev/null @@ -1,52 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, - - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, - - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt index c505a45d2..3e75e0b60 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt @@ -10,6 +10,7 @@ #pragma warning disable 1591 // publicly visible type or member must be documented #nullable enable + #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index 3ba3d6cfe..04263eb00 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt index 986563f37..6b5774e63 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; @@ -323,21 +168,29 @@ namespace SomeNamespace { [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : INTERFACES + [global::Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { - public MassTransit.NewId Value { get; } + public global::MassTransit.NewId Value { get; } - public MyId(MassTransit.NewId value) + public MyId(global::MassTransit.NewId value) { Value = value; } - public static MyId New() => new MyId(MassTransit.NewId.Next()); - public static readonly MyId Empty = new MyId(MassTransit.NewId.Empty); + public static MyId New() => new MyId(global::MassTransit.NewId.Next()); + public static readonly MyId Empty = new MyId(global::MassTransit.NewId.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -346,46 +199,48 @@ namespace SomeNamespace public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || - sourceType == typeof(string) || base.CanConvertFrom - (context, sourceType); + return sourceType == typeof(System.Guid) || sourceType == typeof(global::MassTransit.NewId) + || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { - MassTransit.NewId newIdValue => new MyId(newIdValue), - System.Guid guidValue => new MyId(MassTransit.NewId.FromGuid(guidValue)), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(MassTransit.NewId.FromGuid(result)), + global::MassTransit.NewId newIdValue => new MyId(newIdValue), + global::System.Guid guidValue => new MyId(global::MassTransit.NewId.FromGuid(guidValue)), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(global::MassTransit.NewId.FromGuid(result)), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(System.Guid) || sourceType == typeof(global::MassTransit.NewId) + || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(MassTransit.NewId)) + if (destinationType == typeof(global::MassTransit.NewId)) { return idValue.Value; } - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value.ToGuid(); } @@ -400,16 +255,168 @@ namespace SomeNamespace } } - class MyIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(string) || typeToConvert == typeof(global::System.Guid) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (global::MassTransit.NewId.FromGuid(reader.GetGuid())); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value.ToGuid()); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null")))); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToGuid().ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input))); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input, provider))); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(global::MassTransit.NewId.FromGuid(guid)); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString(string? format, global::System.IFormatProvider? formatProvider) + => Value.ToGuid().ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input))); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input, provider))); +#else + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input))); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(global::MassTransit.NewId.FromGuid(guid)); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.ToGuid().TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.ToGuid().TryFormat(destination, out charsWritten, format); +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, MyId value) + { + parameter.Value = value.Value.ToGuid(); + } + + public override MyId Parse(object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(global::MassTransit.NewId.FromGuid(guidValue)), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(global::MassTransit.NewId.FromGuid(result)), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyId"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { - public override MyId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value.ToGuid(), + value => new MyId(global::MassTransit.NewId.FromGuid(value)), + mappingHints + ) { } + } + + class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(MyId); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) { - return new MyId(MassTransit.NewId.FromGuid(reader.GetGuid())); + serializer.Serialize(writer, value is MyId id ? id.Value : null); } - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyId value, System.Text.Json.JsonSerializerOptions options) + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) { - writer.WriteStringValue(value.Value.ToGuid()); + var guid = serializer.Deserialize(reader); + return guid.HasValue ? new MyId(global::MassTransit.NewId.FromGuid(guid.Value)) : null; } } + } } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt index 8534c7a48..0b0d55e7c 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index 431f6b783..a77d44032 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index 431f6b783..a77d44032 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 96e0c3bb3..320b793f7 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index cf8d1f61d..c7a59d47e 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index 5be631803..631b00ff2 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index f304ae8bd..0249d27de 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt deleted file mode 100644 index 5f282702b..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsUsingGlobalAttribute.verified.txt +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt index d568f0d58..6b2725b74 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; @@ -321,21 +166,29 @@ namespace StronglyTypedIds #nullable enable [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - [System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - readonly partial struct MyId : INTERFACES + [global::Newtonsoft.Json.JsonConverter(typeof(MyIdNewtonsoftJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable { - public MassTransit.NewId Value { get; } + public global::MassTransit.NewId Value { get; } - public MyId(MassTransit.NewId value) + public MyId(global::MassTransit.NewId value) { Value = value; } - public static MyId New() => new MyId(MassTransit.NewId.Next()); - public static readonly MyId Empty = new MyId(MassTransit.NewId.Empty); + public static MyId New() => new MyId(global::MassTransit.NewId.Next()); + public static readonly MyId Empty = new MyId(global::MassTransit.NewId.Empty); + /// public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; return obj is MyId other && Equals(other); @@ -344,46 +197,48 @@ namespace StronglyTypedIds public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); + public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : System.ComponentModel.TypeConverter + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { - public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || - sourceType == typeof(string) || base.CanConvertFrom - (context, sourceType); + return sourceType == typeof(System.Guid) || sourceType == typeof(global::MassTransit.NewId) + || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - - public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) { return value switch { - MassTransit.NewId newIdValue => new MyId(newIdValue), - System.Guid guidValue => new MyId(MassTransit.NewId.FromGuid(guidValue)), - string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new MyId(MassTransit.NewId.FromGuid(result)), + global::MassTransit.NewId newIdValue => new MyId(newIdValue), + global::System.Guid guidValue => new MyId(global::MassTransit.NewId.FromGuid(guidValue)), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(global::MassTransit.NewId.FromGuid(result)), _ => base.ConvertFrom(context, culture, value), }; } - public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) { - return sourceType == typeof(System.Guid) || sourceType == typeof(MassTransit.NewId) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + return sourceType == typeof(System.Guid) || sourceType == typeof(global::MassTransit.NewId) + || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); } - public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) { if (value is MyId idValue) { - if (destinationType == typeof(MassTransit.NewId)) + if (destinationType == typeof(global::MassTransit.NewId)) { return idValue.Value; } - if (destinationType == typeof(System.Guid)) + if (destinationType == typeof(global::System.Guid)) { return idValue.Value.ToGuid(); } @@ -398,15 +253,167 @@ namespace StronglyTypedIds } } - class MyIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(string) || typeToConvert == typeof(global::System.Guid) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (global::MassTransit.NewId.FromGuid(reader.GetGuid())); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value.ToGuid()); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null")))); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToGuid().ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input))); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input, provider))); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(global::MassTransit.NewId.FromGuid(guid)); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString(string? format, global::System.IFormatProvider? formatProvider) + => Value.ToGuid().ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input))); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input, provider))); +#else + => new(global::MassTransit.NewId.FromGuid(global::System.Guid.Parse(input))); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(global::MassTransit.NewId.FromGuid(guid)); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.ToGuid().TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.ToGuid().TryFormat(destination, out charsWritten, format); +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, MyId value) + { + parameter.Value = value.Value.ToGuid(); + } + + public override MyId Parse(object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(global::MassTransit.NewId.FromGuid(guidValue)), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(global::MassTransit.NewId.FromGuid(result)), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyId"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { - public override MyId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value.ToGuid(), + value => new MyId(global::MassTransit.NewId.FromGuid(value)), + mappingHints + ) { } + } + + class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(MyId); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) { - return new MyId(MassTransit.NewId.FromGuid(reader.GetGuid())); + serializer.Serialize(writer, value is MyId id ? id.Value : null); } - public override void Write(System.Text.Json.Utf8JsonWriter writer, MyId value, System.Text.Json.JsonSerializerOptions options) + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) { - writer.WriteStringValue(value.Value.ToGuid()); + var guid = serializer.Deserialize(reader); + return guid.HasValue ? new MyId(global::MassTransit.NewId.FromGuid(guid.Value)) : null; } } + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index d794cbb13..3aea33e05 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt index 3ba3d6cfe..04263eb00 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt @@ -1,36 +1,34 @@ -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { /// /// Place on partial structs to make the type a strongly-typed ID /// - [AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute { /// - /// Make the struct a strongly typed ID + /// Make the struct a strongly typed ID. /// - /// The to use to store the strongly-typed ID value. - /// If not set, uses , which defaults to - /// Converters to create for serializing/deserializing the strongly-typed ID value. - /// If not set, uses , which defaults to - /// and - /// Interfaces and patterns the strongly typed id should implement - /// If not set, uses , which defaults to - /// and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) { - BackingType = backingType; - Converters = converters; - Implementations = implementations; + Template = template; } /// @@ -45,15 +43,6 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(Template template) - { - Template = template; - } - /// /// Make the struct a strongly typed ID, using the default template /// @@ -61,36 +50,32 @@ namespace StronglyTypedIds { } - /// - /// The to use to store the strongly-typed ID value - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// JSON library used to serialize/deserialize strongly-typed ID value - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ -using System; +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES namespace StronglyTypedIds { @@ -98,35 +83,15 @@ namespace StronglyTypedIds /// Used to control the default strongly typed ID values. Apply to an assembly using /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example /// - [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : Attribute + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute { - /// - /// Set the default values used for strongly typed ids - /// - /// The to use to store the strongly-typed ID value. - /// Defaults to - /// JSON library used to serialize/deserialize strongly-typed ID value. - /// Defaults to and - /// Interfaces and patterns the strongly typed id should implement - /// Defaults to and - [Obsolete("This overload is no longer used. Please use the StronglyTypedId(Template) or StronglyTypedId(string) constructor")] - public StronglyTypedIdDefaultsAttribute( - StronglyTypedIdBackingType backingType = StronglyTypedIdBackingType.Default, - StronglyTypedIdConverter converters = StronglyTypedIdConverter.Default, - StronglyTypedIdImplementations implementations = StronglyTypedIdImplementations.Default) - { - BackingType = backingType; - Converters = converters; - Implementations = implementations; - } - /// /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(Template template) + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) { Template = template; } @@ -143,151 +108,31 @@ namespace StronglyTypedIds TemplateName = templateName; } - /// - /// The default to use to store the strongly-typed ID values. - /// - public StronglyTypedIdBackingType BackingType { get; } - - /// - /// The default converters to create for serializing/deserializing strongly-typed ID values. - /// - public StronglyTypedIdConverter Converters { get; } - - /// - /// Interfaces and patterns the strongly typed id should implement - /// - public StronglyTypedIdImplementations Implementations { get; } - /// /// The default template to use to generate the strongly-typed ID value. /// - public string? TemplateName { get; } + public global::StronglyTypedIds.Template? Template { get; } /// /// The default template to use to generate the strongly-typed ID value. /// - public Template? Template { get; } - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The to use to store the value of a strongly-typed ID - /// - internal enum StronglyTypedIdBackingType - { - /// - /// Use the default backing type (either the globally configured default, or Guid) - /// - Default = 0, - - Guid = 1, - Int = 2, - String = 3, - Long = 4, - NullableString = 5, - MassTransitNewId = 6, - } -} -#endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Converters used to to serialize/deserialize strongly-typed ID values - /// - [Flags] - internal enum StronglyTypedIdConverter - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't create any converters for the strongly typed ID - /// - None = 0, - - /// - /// Use the default converters for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, - - /// - /// Creates a for converting from the strongly typed ID to and from a string - /// - TypeConverter = 2, - - /// - /// Creates a Newtonsoft.Json.JsonConverter for serializing the strongly typed id to its primitive value - /// - NewtonsoftJson = 4, - - /// - /// Creates a System.Text.Json.Serialization.JsonConverter for serializing the strongly typed id to its primitive value - /// - SystemTextJson = 8, - - /// - /// Creates an EF Core Value Converter for extracting the primitive value - /// - EfCoreValueConverter = 16, - - /// - /// Creates a Dapper TypeHandler for converting to and from the type - /// - DapperTypeHandler = 32, + public string? TemplateName { get; } } } #endif -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// Interfaces and patterns the strongly typed id should implement - /// - [Flags] - internal enum StronglyTypedIdImplementations - { - // Used with HasFlag, so needs to be 1, 2, 4 etc - - /// - /// Don't implement any additional members for the strongly typed ID - /// - None = 0, +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ - /// - /// Use the default implementations for the strongly typed Id. - /// This will be the value provided in the , which falls back to - /// and - /// - Default = 1, +#pragma warning disable 1591 // publicly visible type or member must be documented - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IEquatable = 2, +#nullable enable - // ReSharper disable once InconsistentNaming - /// - /// Implement the interface - /// - IComparable = 4, - } -} -#endif #if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES using System; diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs index 7ca832f04..4d5e51418 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs +++ b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs @@ -81,7 +81,7 @@ public Task CanGenerateForCustomTemplate() using StronglyTypedIds; namespace SomeNamespace { - [StronglyTypedId("newid")] + [StronglyTypedId("newid-full")] public partial struct MyId {} } """; @@ -207,7 +207,7 @@ public Task CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute() { const string input = """ using StronglyTypedIds; - [assembly:StronglyTypedIdDefaults("newid")] + [assembly:StronglyTypedIdDefaults("newid-full")] [StronglyTypedId] public partial struct MyId {} diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj index 4ef5fe171..caf11f1b1 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj +++ b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj @@ -19,7 +19,7 @@ - + From e33f2e0b0aaa488e161e3f79d13593732b6a3e0c Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 4 Nov 2023 17:03:39 +0000 Subject: [PATCH 12/47] Remove unused diagnostics --- .../InvalidBackingTypeDiagnostic.cs | 22 ---------------- .../Diagnostics/InvalidConverterDiagnostic.cs | 22 ---------------- .../InvalidImplementationsDiagnostic.cs | 16 ------------ .../InvalidBackingTypeDiagnosticTests.cs | 25 ------------------- .../InvalidConverterDiagnosticTests.cs | 25 ------------------- test/StronglyTypedIds.Tests/EqualityTests.cs | 2 +- 6 files changed, 1 insertion(+), 111 deletions(-) delete mode 100644 src/StronglyTypedIds/Diagnostics/InvalidBackingTypeDiagnostic.cs delete mode 100644 src/StronglyTypedIds/Diagnostics/InvalidConverterDiagnostic.cs delete mode 100644 src/StronglyTypedIds/Diagnostics/InvalidImplementationsDiagnostic.cs delete mode 100644 test/StronglyTypedIds.Tests/Diagnostics/InvalidBackingTypeDiagnosticTests.cs delete mode 100644 test/StronglyTypedIds.Tests/Diagnostics/InvalidConverterDiagnosticTests.cs diff --git a/src/StronglyTypedIds/Diagnostics/InvalidBackingTypeDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidBackingTypeDiagnostic.cs deleted file mode 100644 index 44b594690..000000000 --- a/src/StronglyTypedIds/Diagnostics/InvalidBackingTypeDiagnostic.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.CodeAnalysis; - -namespace StronglyTypedIds.Diagnostics -{ - internal static class InvalidBackingTypeDiagnostic - { - internal const string Id = "STI4"; - internal const string Message = "The StronglyTypedIdBackingType value provided is not a valid combination of flags"; - internal const string Title = "Invalid backing type"; - - public static Diagnostic Create(SyntaxNode currentNode) => - Diagnostic.Create( - new DiagnosticDescriptor( - Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), - currentNode.GetLocation()); - - public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) - => new(new DiagnosticDescriptor( - Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), - currentNode.GetLocation()); - } -} \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/InvalidConverterDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidConverterDiagnostic.cs deleted file mode 100644 index a20b771db..000000000 --- a/src/StronglyTypedIds/Diagnostics/InvalidConverterDiagnostic.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.CodeAnalysis; - -namespace StronglyTypedIds.Diagnostics -{ - internal static class InvalidConverterDiagnostic - { - internal const string Id = "STI3"; - internal const string Message = "The StronglyTypedIdConverter value provided is not a valid combination of flags"; - internal const string Title = "Invalid converter"; - - public static Diagnostic Create(SyntaxNode currentNode) => - Diagnostic.Create( - new DiagnosticDescriptor( - Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), - currentNode.GetLocation()); - - public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) - => new(new DiagnosticDescriptor( - Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), - currentNode.GetLocation()); - } -} \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/InvalidImplementationsDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidImplementationsDiagnostic.cs deleted file mode 100644 index c42865151..000000000 --- a/src/StronglyTypedIds/Diagnostics/InvalidImplementationsDiagnostic.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.CodeAnalysis; - -namespace StronglyTypedIds.Diagnostics -{ - internal static class InvalidImplementationsDiagnostic - { - internal const string Id = "STI5"; - internal const string Message = "The StronglyTypedIdImplementations value provided is not a valid combination of flags"; - internal const string Title = "Invalid implementations value"; - - public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) - => new(new DiagnosticDescriptor( - Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), - currentNode.GetLocation()); - } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Diagnostics/InvalidBackingTypeDiagnosticTests.cs b/test/StronglyTypedIds.Tests/Diagnostics/InvalidBackingTypeDiagnosticTests.cs deleted file mode 100644 index ea6c9eff3..000000000 --- a/test/StronglyTypedIds.Tests/Diagnostics/InvalidBackingTypeDiagnosticTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using StronglyTypedIds.Diagnostics; -using Xunit; - -namespace StronglyTypedIds.Tests.Diagnostics -{ - public class InvalidBackingTypeDiagnosticTests - { - [Fact] - public void Create() - { - var diagnostic = InvalidBackingTypeDiagnostic.Create( - SyntaxFactory.ClassDeclaration("A") - .WithMembers(new SyntaxList(SyntaxFactory.StructDeclaration("A")))); - - Assert.Equal(InvalidBackingTypeDiagnostic.Message, diagnostic.GetMessage()); - Assert.Equal(InvalidBackingTypeDiagnostic.Title, diagnostic.Descriptor.Title); - Assert.Equal(InvalidBackingTypeDiagnostic.Id, diagnostic.Id); - Assert.Equal(DiagnosticSeverity.Warning, diagnostic.Severity); - Assert.Equal(Constants.Usage, diagnostic.Descriptor.Category); - } - } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Diagnostics/InvalidConverterDiagnosticTests.cs b/test/StronglyTypedIds.Tests/Diagnostics/InvalidConverterDiagnosticTests.cs deleted file mode 100644 index 6fe0eae2a..000000000 --- a/test/StronglyTypedIds.Tests/Diagnostics/InvalidConverterDiagnosticTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using StronglyTypedIds.Diagnostics; -using Xunit; - -namespace StronglyTypedIds.Tests.Diagnostics -{ - public class InvalidConverterDiagnosticTests - { - [Fact] - public void Create() - { - var diagnostic = InvalidConverterDiagnostic.Create( - SyntaxFactory.ClassDeclaration("A") - .WithMembers(new SyntaxList(SyntaxFactory.StructDeclaration("A")))); - - Assert.Equal(InvalidConverterDiagnostic.Message, diagnostic.GetMessage()); - Assert.Equal(InvalidConverterDiagnostic.Title, diagnostic.Descriptor.Title); - Assert.Equal(InvalidConverterDiagnostic.Id, diagnostic.Id); - Assert.Equal(DiagnosticSeverity.Warning, diagnostic.Severity); - Assert.Equal(Constants.Usage, diagnostic.Descriptor.Category); - } - } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/EqualityTests.cs b/test/StronglyTypedIds.Tests/EqualityTests.cs index 6260cbbb9..0d1ed1684 100644 --- a/test/StronglyTypedIds.Tests/EqualityTests.cs +++ b/test/StronglyTypedIds.Tests/EqualityTests.cs @@ -111,7 +111,7 @@ public void ResultWithDiagnosticHasExpectedEqualityBehaviour() templateName: "Guid", parent: new ParentClass(null, "class", "b", "", null, false)); var diagnostics = new DiagnosticInfo(new DiagnosticDescriptor( - InvalidBackingTypeDiagnostic.Id, InvalidBackingTypeDiagnostic.Title, InvalidBackingTypeDiagnostic.Message, category: Constants.Usage, + NotPartialDiagnostic.Id, NotPartialDiagnostic.Title, NotPartialDiagnostic.Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), Location.Create("somepath.cs", new TextSpan(), new LinePositionSpan(LinePosition.Zero, LinePosition.Zero))); From 3898fff94d2e6008aec4fc43cbc9c1a05bb0b23c Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 4 Nov 2023 21:52:51 +0000 Subject: [PATCH 13/47] Add invalid template name diagnostic --- .../InvalidTemplateNameDiagnostic.cs | 21 ++++++++++++++ src/StronglyTypedIds/Parser.cs | 29 ++++++++++++------- .../Diagnostics/DiagnosticsTests.cs | 26 +++++++++++++++++ 3 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs create mode 100644 test/StronglyTypedIds.Tests/Diagnostics/DiagnosticsTests.cs diff --git a/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs new file mode 100644 index 000000000..f24e6f047 --- /dev/null +++ b/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs @@ -0,0 +1,21 @@ +using Microsoft.CodeAnalysis; + +namespace StronglyTypedIds.Diagnostics; + +internal static class InvalidTemplateNameDiagnostic +{ + internal const string Id = "STI8"; + internal const string Message = "The template name must not be null or whitespace."; + internal const string Title = "Invalid template name"; + + public static Diagnostic Create(SyntaxNode currentNode) => + Diagnostic.Create( + new DiagnosticDescriptor( + Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), + currentNode.GetLocation()); + + public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) + => new(new DiagnosticDescriptor( + Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), + currentNode.GetLocation()); +} \ No newline at end of file diff --git a/src/StronglyTypedIds/Parser.cs b/src/StronglyTypedIds/Parser.cs index e3bb5f6fd..4c5feb813 100644 --- a/src/StronglyTypedIds/Parser.cs +++ b/src/StronglyTypedIds/Parser.cs @@ -39,7 +39,7 @@ internal static class Parser continue; } - hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName); + hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName, ref diagnostics); } var hasPartialModifier = false; @@ -114,7 +114,7 @@ internal static class Parser continue; } - hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName); + hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName, ref diagnostics); if (hasMisconfiguredInput) { @@ -139,23 +139,22 @@ internal static class Parser return new Result<(Defaults, bool)>((defaults, true), errors); } - private static bool GetConstructorValues(AttributeData attribute, out Template? template, out string? templateName) + private static bool GetConstructorValues(AttributeData attribute, out Template? template, out string? templateName, ref List? diagnostics) { var hasMisconfiguredInput = false; template = null; templateName = null; - if (!attribute.ConstructorArguments.IsEmpty) + if (attribute.ConstructorArguments is { IsEmpty: false } args) { // make sure we don't have any errors - ImmutableArray args = attribute.ConstructorArguments; - foreach (TypedConstant arg in args) { if (arg.Kind == TypedConstantKind.Error) { // have an error, so don't try and do any generation hasMisconfiguredInput = true; + break; } } @@ -168,15 +167,20 @@ private static bool GetConstructorValues(AttributeData attribute, out Template? templateName = args[0].Value as string; if (string.IsNullOrWhiteSpace(templateName)) { - // TODO: add diagnostic + if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } s) + { + diagnostics ??= new(); + diagnostics.Add(InvalidTemplateNameDiagnostic.CreateInfo(s)); + } + hasMisconfiguredInput = true; } } } - if (!attribute.NamedArguments.IsEmpty) + if (attribute.NamedArguments is { IsEmpty: false } namedArgs) { - foreach (KeyValuePair arg in attribute.NamedArguments) + foreach (KeyValuePair arg in namedArgs) { TypedConstant typedConstant = arg.Value; if (typedConstant.Kind == TypedConstantKind.Error) @@ -194,7 +198,12 @@ private static bool GetConstructorValues(AttributeData attribute, out Template? templateName = typedConstant.Value as string; if (string.IsNullOrWhiteSpace(templateName)) { - // TODO: add diagnostic + if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } s) + { + diagnostics ??= new(); + diagnostics.Add(InvalidTemplateNameDiagnostic.CreateInfo(s)); + } + hasMisconfiguredInput = true; } } diff --git a/test/StronglyTypedIds.Tests/Diagnostics/DiagnosticsTests.cs b/test/StronglyTypedIds.Tests/Diagnostics/DiagnosticsTests.cs new file mode 100644 index 000000000..f42d8fc05 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Diagnostics/DiagnosticsTests.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using StronglyTypedIds.Diagnostics; +using VerifyXunit; +using Xunit; + +namespace StronglyTypedIds.Tests.Diagnostics; + +public class DiagnosticsTests +{ + [Theory] + [InlineData("null")] + [InlineData("\"\"")] + [InlineData("\" \"")] + public void EmptyTemplateGivesInvalidTemplateNameDiagnostic(string template) + { + var input = $$""" + using StronglyTypedIds; + + [StronglyTypedId({{template}})] + public partial struct MyId {} + """; + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + + Assert.Contains(diagnostics, diagnostic => diagnostic.Id == InvalidTemplateNameDiagnostic.Id); + } +} \ No newline at end of file From 14bc33b76af63521c65206d8c3cdbec501d4f398 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sun, 5 Nov 2023 13:16:39 +0000 Subject: [PATCH 14/47] Update handling of unknown templates (adds a diagnostic) --- .../Diagnostics/UnknownTemplateDiagnostic.cs | 15 + src/StronglyTypedIds/Parser.cs | 49 ++- .../StronglyTypedIdGenerator.cs | 138 ++++--- src/StronglyTypedIds/StructToGenerate.cs | 31 +- .../Diagnostics/DiagnosticsTests.cs | 26 -- .../Diagnostics/NotPartialDiagnosticTests.cs | 23 -- .../DiagnosticsTests.cs | 95 +++++ test/StronglyTypedIds.Tests/EqualityTests.cs | 25 +- .../Snapshots/NoGeneratedIds.verified.txt | 154 ++++++++ ...ttributesGeneratesWithDefault.verified.txt | 367 ------------------ .../StronglyTypedIdGeneratorTests.cs | 19 - 11 files changed, 435 insertions(+), 507 deletions(-) create mode 100644 src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs delete mode 100644 test/StronglyTypedIds.Tests/Diagnostics/DiagnosticsTests.cs delete mode 100644 test/StronglyTypedIds.Tests/Diagnostics/NotPartialDiagnosticTests.cs create mode 100644 test/StronglyTypedIds.Tests/DiagnosticsTests.cs create mode 100644 test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt diff --git a/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs new file mode 100644 index 000000000..825baa539 --- /dev/null +++ b/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs @@ -0,0 +1,15 @@ +using Microsoft.CodeAnalysis; + +namespace StronglyTypedIds.Diagnostics; + +internal static class UnknownTemplateDiagnostic +{ + internal const string Id = "STI7"; + internal const string Title = "Unknown .typedid template"; + + public static DiagnosticInfo CreateInfo(LocationInfo location, string name) + => new(new DiagnosticDescriptor( + Id, Title, $"Could not find '{name}.typedid' template. Ensure the template exists and has a build action of 'Additional Files'.", + category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), + location.ToLocation()); +} \ No newline at end of file diff --git a/src/StronglyTypedIds/Parser.cs b/src/StronglyTypedIds/Parser.cs index 4c5feb813..4c75e9344 100644 --- a/src/StronglyTypedIds/Parser.cs +++ b/src/StronglyTypedIds/Parser.cs @@ -1,6 +1,4 @@ using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -28,6 +26,7 @@ internal static class Parser List? diagnostics = null; Template? template = null; string? templateName = null; + LocationInfo? templateLocation = null; foreach (AttributeData attribute in structSymbol.GetAttributes()) { @@ -39,7 +38,7 @@ internal static class Parser continue; } - hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName, ref diagnostics); + hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName, out templateLocation, ref diagnostics); } var hasPartialModifier = false; @@ -73,7 +72,7 @@ internal static class Parser var toGenerate = template.HasValue ? new StructToGenerate(name: name, nameSpace: nameSpace, template: template.Value, parent: parentClass) - : new StructToGenerate(name: name, nameSpace: nameSpace, templateName: templateName, parent: parentClass); + : new StructToGenerate(name: name, nameSpace: nameSpace, templateName: templateName, templateLocation: templateLocation!, parent: parentClass); return new Result<(StructToGenerate, bool)>((toGenerate, true), errors); } @@ -90,9 +89,13 @@ internal static class Parser // We only return the first config that we find string? templateName = null; Template? template = null; + LocationInfo? templateLocation = null; List? diagnostics = null; bool hasMisconfiguredInput = false; + bool hasMultiple = false; + // if we have multiple attributes we still check them, so that we can add extra diagnostics if necessary + // the "first" one found won't be flagged as a duplicate though. foreach (AttributeData attribute in assemblyAttributes) { if (!((attribute.AttributeClass?.Name == "StronglyTypedIdDefaultsAttribute" || @@ -105,22 +108,15 @@ internal static class Parser if (!string.IsNullOrWhiteSpace(templateName) || template.HasValue) { + hasMultiple = true; if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } s) { diagnostics ??= new(); diagnostics.Add(MultipleAssemblyAttributeDiagnostic.CreateInfo(s)); } - - continue; } - hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName, ref diagnostics); - - if (hasMisconfiguredInput) - { - // skip further generator execution and let compiler generate the errors - break; - } + hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName, out templateLocation, ref diagnostics); } var errors = diagnostics is null @@ -133,17 +129,18 @@ internal static class Parser } var defaults = template.HasValue - ? new Defaults(template.Value) - : new Defaults(templateName!); + ? new Defaults(template.Value, hasMultiple) + : new Defaults(templateName!, templateLocation!, hasMultiple); return new Result<(Defaults, bool)>((defaults, true), errors); } - private static bool GetConstructorValues(AttributeData attribute, out Template? template, out string? templateName, ref List? diagnostics) + private static bool GetConstructorValues(AttributeData attribute, out Template? template, out string? templateName, out LocationInfo? templateLocation, ref List? diagnostics) { var hasMisconfiguredInput = false; template = null; templateName = null; + templateLocation = null; if (attribute.ConstructorArguments is { IsEmpty: false } args) { @@ -165,9 +162,10 @@ private static bool GetConstructorValues(AttributeData attribute, out Template? else { templateName = args[0].Value as string; + var syntaxNode = attribute.ApplicationSyntaxReference?.GetSyntax(); if (string.IsNullOrWhiteSpace(templateName)) { - if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } s) + if (syntaxNode is { } s) { diagnostics ??= new(); diagnostics.Add(InvalidTemplateNameDiagnostic.CreateInfo(s)); @@ -175,6 +173,13 @@ private static bool GetConstructorValues(AttributeData attribute, out Template? hasMisconfiguredInput = true; } + else + { + if (syntaxNode is { } s) + { + templateLocation = LocationInfo.CreateFrom(s); + } + } } } @@ -196,9 +201,10 @@ private static bool GetConstructorValues(AttributeData attribute, out Template? else { templateName = typedConstant.Value as string; + var syntaxNode = attribute.ApplicationSyntaxReference?.GetSyntax(); if (string.IsNullOrWhiteSpace(templateName)) { - if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } s) + if (syntaxNode is { } s) { diagnostics ??= new(); diagnostics.Add(InvalidTemplateNameDiagnostic.CreateInfo(s)); @@ -206,6 +212,13 @@ private static bool GetConstructorValues(AttributeData attribute, out Template? hasMisconfiguredInput = true; } + else + { + if (syntaxNode is { } s) + { + templateLocation = LocationInfo.CreateFrom(s); + } + } } break; diff --git a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs index d142efd1f..bdafcd3f8 100644 --- a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs +++ b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs @@ -1,11 +1,12 @@ using System; -using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; +using StronglyTypedIds.Diagnostics; namespace StronglyTypedIds { @@ -33,9 +34,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) Name: Path.GetFileNameWithoutExtension(template.Path), Content: template.GetText(ct)?.ToString())); - var templatesWithErrors = allTemplates - .Where(template => string.IsNullOrWhiteSpace(template.Name) || template.Content is null); - var templates = allTemplates .Where(template => !string.IsNullOrWhiteSpace(template.Name) && template.Content is not null) .Collect(); @@ -62,49 +60,62 @@ public void Initialize(IncrementalGeneratorInitializationContext context) defaultsAndDiagnostics.SelectMany((x, _) => x.Errors), static (context, info) => context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location))); - // context.RegisterSourceOutput( - // templatesWithErrors, - // static (context, info) => context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location))); - IncrementalValuesProvider structs = structAndDiagnostics .Where(static x => x.Value.valid) .Select((result, _) => result.Value.info); - - IncrementalValueProvider defaultTemplateContent = defaultsAndDiagnostics + IncrementalValueProvider<(string? Content, bool isValid, DiagnosticInfo? Diagnostic)> defaultTemplateContent = defaultsAndDiagnostics .Where(static x => x.Value.valid) .Select((result, _) => result.Value.defaults) .Collect() .Combine(templates) .Select((all, _) => { - // we can only use one default attribute - // more than one is an error, but lets do our best - var defaults = all.Left.IsDefaultOrEmpty ? (Defaults?) null : all.Left[0]; - if (defaults?.Template is { } templateId) + if (all.Left.IsDefaultOrEmpty) + { + // no default attributes, valid, but no content + return (null, true, null); + } + + // technically we can never have more than one `Defaults` here + // but check for it just in case + if (all.Left is {IsDefaultOrEmpty: false, Length: > 1}) + { + return (null, false, null); + } + + var defaults = all.Left[0]; + if (defaults.HasMultiple) + { + // not valid + return (null, false, null); + } + + if (defaults.Template is { } templateId) { - return EmbeddedSources.GetTemplate(templateId); + // Explicit template + return (EmbeddedSources.GetTemplate(templateId), true, (DiagnosticInfo?) null); } - var defaultsTemplateName = defaults?.TemplateName; + // We have already checked for a null template name and flagged it as an error + var defaultsTemplateName = defaults.TemplateName; if(!string.IsNullOrEmpty(defaultsTemplateName)) { foreach (var templateDetails in all.Right) { if (string.Equals(templateDetails.Name, defaultsTemplateName, StringComparison.Ordinal)) { - // This _could_ be empty, but we use it anyway (and add a warning in the template) - return templateDetails.Content; + // This _could_ be empty, but we use it anyway (and add a comment in the template) + return (templateDetails.Content ?? GetEmptyTemplateContent(defaultsTemplateName!), true, null); } } - - // TODO: Add diagnostic that couldn't find a template with the right name - // TODO: Add a warning in a comment to the code too? - // context.ReportDiagnostic(); + + // Template name specified, but we don't have a template for it + return (null, false, UnknownTemplateDiagnostic.CreateInfo(defaults!.TemplateLocation!, defaultsTemplateName!)); } - - // no default - return null; + + // only get here if the template name was null/empty, which is already reported + return (null, false, null); }); var structsWithDefaultsAndTemplates = structs @@ -118,41 +129,26 @@ public void Initialize(IncrementalGeneratorInitializationContext context) private static void Execute( StructToGenerate idToGenerate, ImmutableArray<(string Path, string Name, string? Content)> templates, - string? defaultTemplateContent, + (string? Content, bool IsValid, DiagnosticInfo? Diagnostics) defaults, SourceProductionContext context) { var sb = new StringBuilder(); - - string? template = null!; - if (idToGenerate.Template is { } templateId) + if (defaults.Diagnostics is { } diagnostic) { - template = EmbeddedSources.GetTemplate(templateId); + // report error with the default template + context.ReportDiagnostic(Diagnostic.Create(diagnostic.Descriptor, diagnostic.Location)); } - else if(!string.IsNullOrEmpty(idToGenerate.TemplateName)) - { - foreach (var templateDetails in templates) - { - if (string.Equals(templateDetails.Name, idToGenerate.TemplateName, StringComparison.Ordinal)) - { - template = templateDetails.Content; - break; - } - } - // TODO: Add diagnostic that couldn't find a template with the right name - // context.ReportDiagnostic(); - } - - if (string.IsNullOrEmpty(template)) + if (!TryGetTemplateContent(idToGenerate, templates, defaults.IsValid, defaults.Content, context, out var templateContent)) { - template = defaultTemplateContent ?? EmbeddedSources.GetTemplate(Template.Guid); + return; } var result = SourceGenerationHelper.CreateId( idToGenerate.NameSpace, idToGenerate.Name, idToGenerate.Parent, - template!, + templateContent, sb); var fileName = SourceGenerationHelper.CreateSourceName( @@ -161,5 +157,53 @@ private static void Execute( idToGenerate.Name); context.AddSource(fileName, SourceText.From(result, Encoding.UTF8)); } + + private static bool TryGetTemplateContent( + in StructToGenerate idToGenerate, + in ImmutableArray<(string Path, string Name, string? Content)> templates, + bool haveValidDefault, + string? defaultContent, + in SourceProductionContext context, + [NotNullWhen(true)] out string? templateContent) + { + // built-in template specified + if (idToGenerate.Template is { } templateId) + { + templateContent = EmbeddedSources.GetTemplate(templateId); + return true; + } + + // custom template specified + if (!string.IsNullOrEmpty(idToGenerate.TemplateName)) + { + foreach (var templateDetails in templates) + { + if (string.Equals(templateDetails.Name, idToGenerate.TemplateName, StringComparison.Ordinal)) + { + templateContent = templateDetails.Content ?? GetEmptyTemplateContent(idToGenerate.TemplateName!); + return true; + } + } + + // the template wasn't found, so it must be invalid. Don't generate anything + var info = UnknownTemplateDiagnostic.CreateInfo(idToGenerate.TemplateLocation!, idToGenerate.TemplateName!); + context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location)); + templateContent = null; + return false; + } + + // nothing specified, use the default (if we have one) + if (haveValidDefault) + { + templateContent = defaultContent ?? EmbeddedSources.GetTemplate(Template.Guid); + return true; + } + + templateContent = null; + return false; + } + + private static string GetEmptyTemplateContent(string templateName) + => $"// The {templateName}.typeid template was empty, you'll need to add some content"; } } \ No newline at end of file diff --git a/src/StronglyTypedIds/StructToGenerate.cs b/src/StronglyTypedIds/StructToGenerate.cs index af0596186..3f3945ba9 100644 --- a/src/StronglyTypedIds/StructToGenerate.cs +++ b/src/StronglyTypedIds/StructToGenerate.cs @@ -1,17 +1,19 @@ using System; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; namespace StronglyTypedIds; internal readonly record struct StructToGenerate { - public StructToGenerate(string name, string nameSpace, string? templateName, ParentClass? parent) + public StructToGenerate(string name, string nameSpace, string? templateName, ParentClass? parent, LocationInfo templateLocation) { Name = name; NameSpace = nameSpace; TemplateName = templateName; Template = null; Parent = parent; + TemplateLocation = templateLocation; } public StructToGenerate(string name, string nameSpace, Template template, ParentClass? parent) @@ -21,6 +23,7 @@ public StructToGenerate(string name, string nameSpace, Template template, Parent TemplateName = null; Template = template; Parent = parent; + TemplateLocation = null; } public string Name { get; } @@ -28,6 +31,7 @@ public StructToGenerate(string name, string nameSpace, Template template, Parent public string? TemplateName { get; } public Template? Template { get; } public ParentClass? Parent { get; } + public LocationInfo? TemplateLocation { get; } } internal sealed record Result(TValue Value, EquatableArray Errors) @@ -40,20 +44,39 @@ internal sealed record Result(TValue Value, EquatableArray Location.Create(FilePath, TextSpan, LineSpan); + + public static LocationInfo CreateFrom(SyntaxNode node) + { + var location = node.GetLocation(); + // assuming that source tree is always non-null here... hopefully that's the case + return new LocationInfo(location.SourceTree!.FilePath, location.SourceSpan, location.GetLineSpan().Span); + } +} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Diagnostics/DiagnosticsTests.cs b/test/StronglyTypedIds.Tests/Diagnostics/DiagnosticsTests.cs deleted file mode 100644 index f42d8fc05..000000000 --- a/test/StronglyTypedIds.Tests/Diagnostics/DiagnosticsTests.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Threading.Tasks; -using StronglyTypedIds.Diagnostics; -using VerifyXunit; -using Xunit; - -namespace StronglyTypedIds.Tests.Diagnostics; - -public class DiagnosticsTests -{ - [Theory] - [InlineData("null")] - [InlineData("\"\"")] - [InlineData("\" \"")] - public void EmptyTemplateGivesInvalidTemplateNameDiagnostic(string template) - { - var input = $$""" - using StronglyTypedIds; - - [StronglyTypedId({{template}})] - public partial struct MyId {} - """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); - - Assert.Contains(diagnostics, diagnostic => diagnostic.Id == InvalidTemplateNameDiagnostic.Id); - } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Diagnostics/NotPartialDiagnosticTests.cs b/test/StronglyTypedIds.Tests/Diagnostics/NotPartialDiagnosticTests.cs deleted file mode 100644 index a92899fc2..000000000 --- a/test/StronglyTypedIds.Tests/Diagnostics/NotPartialDiagnosticTests.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using StronglyTypedIds.Diagnostics; -using Xunit; - -namespace StronglyTypedIds.Tests.Diagnostics -{ - public class NotPartialDiagnosticTests - { - [Fact] - public void Create() - { - var diagnostic = NotPartialDiagnostic.Create( - SyntaxFactory.StructDeclaration("A")); - - Assert.Equal(NotPartialDiagnostic.Message, diagnostic.GetMessage()); - Assert.Equal(NotPartialDiagnostic.Title, diagnostic.Descriptor.Title); - Assert.Equal(NotPartialDiagnostic.Id, diagnostic.Id); - Assert.Equal(DiagnosticSeverity.Warning, diagnostic.Severity); - Assert.Equal(Constants.Usage, diagnostic.Descriptor.Category); - } - } -} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/DiagnosticsTests.cs b/test/StronglyTypedIds.Tests/DiagnosticsTests.cs new file mode 100644 index 000000000..4c1de7a82 --- /dev/null +++ b/test/StronglyTypedIds.Tests/DiagnosticsTests.cs @@ -0,0 +1,95 @@ +using System.Threading.Tasks; +using StronglyTypedIds.Diagnostics; +using VerifyTests; +using VerifyXunit; +using Xunit; + +namespace StronglyTypedIds.Tests.Diagnostics; + +[UsesVerify] +public class DiagnosticsTests +{ + public const string NoIdGenerationSnapshotName = "NoGeneratedIds"; + + [Theory] + [InlineData("null")] + [InlineData("\"\"")] + [InlineData("\" \"")] + public Task EmptyTemplate_GivesInvalidTemplateNameDiagnostic_AndDoesntGenerate(string template) + { + var input = $$""" + using StronglyTypedIds; + + [StronglyTypedId({{template}})] + public partial struct MyId {} + """; + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + + Assert.Contains(diagnostics, diagnostic => diagnostic.Id == InvalidTemplateNameDiagnostic.Id); + + return Verifier.Verify(output) + .DisableRequireUniquePrefix() + .UseDirectory("Snapshots") + .UseFileName(NoIdGenerationSnapshotName); + } + + [Fact] + public Task MultipleAssemblyAttributes_GivesMultipleAttributeDiagnostic_AndDoesntGenerate() + { + const string input = """ + using StronglyTypedIds; + [assembly:StronglyTypedIdDefaults(Template.Int)] + [assembly:StronglyTypedIdDefaults(Template.Long)] + + [StronglyTypedId] + public partial struct MyId {} + """; + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + + Assert.Contains(diagnostics, diagnostic => diagnostic.Id == MultipleAssemblyAttributeDiagnostic.Id); + + return Verifier.Verify(output) + .DisableRequireUniquePrefix() + .UseDirectory("Snapshots") + .UseFileName(NoIdGenerationSnapshotName); + } + + [Fact] + public Task InvalidTemplate_GivesDiagnostic_AndDoesntGenerate() + { + const string input = """ + using StronglyTypedIds; + + [StronglyTypedId("some-template")] + public partial struct MyId {} + """; + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + + Assert.Contains(diagnostics, diagnostic => diagnostic.Id == UnknownTemplateDiagnostic.Id); + + return Verifier.Verify(output) + .DisableRequireUniquePrefix() + .UseDirectory("Snapshots") + .UseFileName(NoIdGenerationSnapshotName); + } + + [Fact] + public Task InvalidTemplateInDefaultsAttribute_GivesDiagnostic_AndDoesntGenerate() + { + const string input = """ + using StronglyTypedIds; + [assembly:StronglyTypedIdDefaults("some-template")] + + [StronglyTypedId] + public partial struct MyId {} + """; + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + + Assert.Contains(diagnostics, diagnostic => diagnostic.Id == UnknownTemplateDiagnostic.Id); + + return Verifier.Verify(output) + .DisableRequireUniquePrefix() + .UseDirectory("Snapshots") + .UseFileName(NoIdGenerationSnapshotName); + } +} \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/EqualityTests.cs b/test/StronglyTypedIds.Tests/EqualityTests.cs index 0d1ed1684..5d5c0e9e2 100644 --- a/test/StronglyTypedIds.Tests/EqualityTests.cs +++ b/test/StronglyTypedIds.Tests/EqualityTests.cs @@ -43,11 +43,30 @@ public void StructToGenerateHasExpectedEqualityBehaviour() Assert.True(instance1.Equals(instance2)); Assert.True(instance1 == instance2); + StructToGenerate GetStruct() => + new( + name: "MyStruct", + nameSpace: "MyNamespace", + template: Template.Guid, + parent: null); + } + + [Fact] + public void StructToGenerateWithTemplateAndLocationHasExpectedEqualityBehaviour() + { + var instance1 = GetStruct(); + var instance2 = GetStruct(); + + Assert.Equal(instance1, instance2); + Assert.True(instance1.Equals(instance2)); + Assert.True(instance1 == instance2); + StructToGenerate GetStruct() => new( name: "MyStruct", nameSpace: "MyNamespace", templateName: "Guid", + templateLocation: new LocationInfo("Some path", new TextSpan(0, 100), new LinePositionSpan(new LinePosition(23, 2), new LinePosition(23, 15))), parent: null); } @@ -66,7 +85,7 @@ StructToGenerate GetStruct() return new StructToGenerate( name: "MyStruct", nameSpace: "MyNamespace", - templateName: "Guid", + template: Template.Guid, parent: new ParentClass(null, "class", "b", "", null, false)); } } @@ -86,7 +105,7 @@ public void ResultWithoutDiagnosticHasExpectedEqualityBehaviour() var instance = new StructToGenerate( name: "MyStruct", nameSpace: "MyNamespace", - templateName: "Guid", + template: Template.Guid, parent: new ParentClass(null, "class", "b", "", null, false)); return new Result<(StructToGenerate, bool)>((instance, true), new EquatableArray()); @@ -108,7 +127,7 @@ public void ResultWithDiagnosticHasExpectedEqualityBehaviour() var instance = new StructToGenerate( name: "MyStruct", nameSpace: "MyNamespace", - templateName: "Guid", + template: Template.Guid, parent: new ParentClass(null, "class", "b", "", null, false)); var diagnostics = new DiagnosticInfo(new DiagnosticDescriptor( NotPartialDiagnostic.Id, NotPartialDiagnostic.Title, NotPartialDiagnostic.Message, category: Constants.Usage, diff --git a/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt new file mode 100644 index 000000000..de5f8b4ce --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt @@ -0,0 +1,154 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +namespace StronglyTypedIds +{ + /// + /// Place on partial structs to make the type a strongly-typed ID + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdAttribute : global::System.Attribute + { + /// + /// Make the struct a strongly typed ID. + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) + { + Template = template; + } + + /// + /// Make the struct a strongly typed ID. + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// Make the struct a strongly typed ID, using the default template + /// + public StronglyTypedIdAttribute() + { + } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public global::StronglyTypedIds.Template? Template { get; } + + /// + /// The template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +namespace StronglyTypedIds +{ + /// + /// Used to control the default strongly typed ID values. Apply to an assembly using + /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] + [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] + internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute + { + /// + /// Set the default template to use for strongly typed IDs + /// + /// The built-in template to use to generate the ID. + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) + { + Template = template; + } + + /// + /// Set the default template to use for strongly typed IDs + /// + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName) + { + TemplateName = templateName; + } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public global::StronglyTypedIds.Template? Template { get; } + + /// + /// The default template to use to generate the strongly-typed ID value. + /// + public string? TemplateName { get; } + } +} +#endif +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + +#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES + +using System; + +namespace StronglyTypedIds +{ + /// + /// The built-in template to use to generate the strongly-typed ID + /// + internal enum Template + { + Guid, + Int, + String, + Long, + NullableString, + } +} +#endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt deleted file mode 100644 index 04263eb00..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.MultipleAssemblyAttributesGeneratesWithDefault.verified.txt +++ /dev/null @@ -1,367 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - NullableString, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] - [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] - partial struct MyId : -#if NET6_0_OR_GREATER - global::System.ISpanFormattable, -#endif -#if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, -#endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public global::System.Guid Value { get; } - - public MyId(global::System.Guid value) - { - Value = value; - } - - public static MyId New() => new MyId(global::System.Guid.NewGuid()); - public static readonly MyId Empty = new MyId(global::System.Guid.Empty); - - /// - public bool Equals(MyId other) => this.Value.Equals(other.Value); - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is MyId other && Equals(other); - } - - public override int GetHashCode() => Value.GetHashCode(); - - public override string ToString() => Value.ToString(); - - public static bool operator ==(MyId a, MyId b) => a.Equals(b); - public static bool operator !=(MyId a, MyId b) => !(a == b); - - /// - public int CompareTo(MyId other) => Value.CompareTo(other.Value); - - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - { - return value switch - { - global::System.Guid guidValue => new MyId(guidValue), - string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), - _ => base.ConvertFrom(context, culture, value), - }; - } - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is MyId idValue) - { - if (destinationType == typeof(global::System.Guid)) - { - return idValue.Value; - } - - if (destinationType == typeof(string)) - { - return idValue.Value.ToString(); - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetGuid()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - -#if NET6_0_OR_GREATER - public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value.ToString()); -#endif - } - - public static MyId Parse(string input) - => new(global::System.Guid.Parse(input)); - -#if NET7_0_OR_GREATER - /// - public static MyId Parse(string input, global::System.IFormatProvider? provider) - => new(global::System.Guid.Parse(input, provider)); - - /// - public static bool TryParse( - [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, - global::System.IFormatProvider? provider, - out MyId result) - { - if (input is null) - { - result = default; - return false; - } - - if (global::System.Guid.TryParse(input, provider, out var guid)) - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } -#endif - - /// - public string ToString( -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - string? format, - global::System.IFormatProvider? formatProvider) - => Value.ToString(format, formatProvider); - -#if NETCOREAPP2_1_OR_GREATER - public static MyId Parse(global::System.ReadOnlySpan input) - => new(global::System.Guid.Parse(input)); -#endif - -#if NET6_0_OR_GREATER -#if NET7_0_OR_GREATER - /// -#endif - public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) -#if NET7_0_OR_GREATER - => new(global::System.Guid.Parse(input, provider)); -#else - => new(global::System.Guid.Parse(input)); -#endif - -#if NET7_0_OR_GREATER - /// -#endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) - { -#if NET7_0_OR_GREATER - if (global::System.Guid.TryParse(input, provider, out var guid)) -#else - if (global::System.Guid.TryParse(input, out var guid)) -#endif - { - result = new(guid); - return true; - } - else - { - result = default; - return false; - } - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => Value.TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, -#if NET7_0_OR_GREATER - [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] -#endif - global::System.ReadOnlySpan format = default) - => Value.TryFormat(destination, out charsWritten, format); -#endif - } diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs index 4d5e51418..ebaf90a20 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs +++ b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs @@ -221,25 +221,6 @@ public partial struct MyId {} .UseDirectory("Snapshots"); } - [Fact] - public Task MultipleAssemblyAttributesGeneratesWithDefault() - { - const string input = """ - using StronglyTypedIds; - [assembly:StronglyTypedIdDefaults("int")] - [assembly:StronglyTypedIdDefaults("long")] - - [StronglyTypedId] - public partial struct MyId {} - """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); - - Assert.Contains(diagnostics, diagnostic => diagnostic.Id == MultipleAssemblyAttributeDiagnostic.Id); - - return Verifier.Verify(output) - .UseDirectory("Snapshots"); - } - [Fact] public Task CanGenerateMultipleIdsWithSameName() { From 2b69c206761d76023c124c3f49bfba8e8bee0691 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sun, 5 Nov 2023 22:37:57 +0000 Subject: [PATCH 15/47] Don't do special behaviour for custom templates + add diagnostic for invalid templates --- src/StronglyTypedIds/DiagnosticInfo.cs | 6 ++- .../Diagnostics/DiagnosticHelper.cs | 41 ++++++++++++++ .../Diagnostics/UnknownTemplateDiagnostic.cs | 14 +++-- src/StronglyTypedIds/EquatableArray.cs | 5 ++ .../SourceGenerationHelper.cs | 10 +--- .../StronglyTypedIdGenerator.cs | 53 ++++++++++++------- .../Templates/guid-full.typedid | 2 + .../Templates/int-full.typedid | 2 + .../Templates/long-full.typedid | 2 + .../Templates/newid-full.typedid | 2 + .../Templates/nullablestring-full.typedid | 2 + .../Templates/string-full.typedid | 2 + 12 files changed, 109 insertions(+), 32 deletions(-) create mode 100644 src/StronglyTypedIds/Diagnostics/DiagnosticHelper.cs diff --git a/src/StronglyTypedIds/DiagnosticInfo.cs b/src/StronglyTypedIds/DiagnosticInfo.cs index 8fd036237..ce57b8bf3 100644 --- a/src/StronglyTypedIds/DiagnosticInfo.cs +++ b/src/StronglyTypedIds/DiagnosticInfo.cs @@ -4,12 +4,16 @@ namespace StronglyTypedIds; internal sealed record DiagnosticInfo { - public DiagnosticInfo(DiagnosticDescriptor descriptor, Location location) + public DiagnosticInfo(DiagnosticDescriptor descriptor, Location location, string? messageArg = null, EquatableArray<(string, string)> properties = default) { Descriptor = descriptor; Location = location; + MessageArg = messageArg; + Properties = properties; } public DiagnosticDescriptor Descriptor { get; } public Location Location { get; } + public string? MessageArg { get; } + public EquatableArray<(string, string)> Properties { get; } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/DiagnosticHelper.cs b/src/StronglyTypedIds/Diagnostics/DiagnosticHelper.cs new file mode 100644 index 000000000..71e81a024 --- /dev/null +++ b/src/StronglyTypedIds/Diagnostics/DiagnosticHelper.cs @@ -0,0 +1,41 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace StronglyTypedIds.Diagnostics; + +internal static class DiagnosticHelper +{ + public static void ReportDiagnostic(this SourceProductionContext context, DiagnosticInfo info) + { + var diagnostic = CreateDiagnostic(info); + + context.ReportDiagnostic(diagnostic); + } + + public static Diagnostic CreateDiagnostic(DiagnosticInfo info) + { + var messageArgs = info.MessageArg is { } arg + ? new object[] {arg} + : null; + + ImmutableDictionary? properties = null; + if (info.Properties is {Count: > 0} props) + { + var dict = ImmutableDictionary.CreateBuilder(); + foreach (var prop in props.GetArray()!) + { + dict.Add(prop.Item1, prop.Item2); + } + + properties = dict.ToImmutable()!; + } + + + var diagnostic = Diagnostic.Create( + descriptor: info.Descriptor, + location: info.Location, + messageArgs: messageArgs, + properties: properties); + return diagnostic; + } +} \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs index 825baa539..6fc3a501d 100644 --- a/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs @@ -6,10 +6,16 @@ internal static class UnknownTemplateDiagnostic { internal const string Id = "STI7"; internal const string Title = "Unknown .typedid template"; + internal const string TemplateName = nameof(TemplateName); public static DiagnosticInfo CreateInfo(LocationInfo location, string name) - => new(new DiagnosticDescriptor( - Id, Title, $"Could not find '{name}.typedid' template. Ensure the template exists and has a build action of 'Additional Files'.", - category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), - location.ToLocation()); + => new(CreateDescriptor(), + location.ToLocation(), + name, + new EquatableArray<(string, string)>(new[] {(TemplateName, name)})); + + public static DiagnosticDescriptor CreateDescriptor() + => new( + Id, Title, "Could not find '{0}.typedid' template. Ensure the template exists and has a build action of 'Additional Files'.", + category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true); } \ No newline at end of file diff --git a/src/StronglyTypedIds/EquatableArray.cs b/src/StronglyTypedIds/EquatableArray.cs index 33d48db8c..70c1030e0 100644 --- a/src/StronglyTypedIds/EquatableArray.cs +++ b/src/StronglyTypedIds/EquatableArray.cs @@ -67,6 +67,11 @@ public ReadOnlySpan AsSpan() return _array.AsSpan(); } + /// + /// Gets the underlying array if there is one + /// + public T[]? GetArray() => _array; + /// IEnumerator IEnumerable.GetEnumerator() { diff --git a/src/StronglyTypedIds/SourceGenerationHelper.cs b/src/StronglyTypedIds/SourceGenerationHelper.cs index d113056d0..c435d7fa5 100644 --- a/src/StronglyTypedIds/SourceGenerationHelper.cs +++ b/src/StronglyTypedIds/SourceGenerationHelper.cs @@ -5,18 +5,12 @@ namespace StronglyTypedIds { internal static class SourceGenerationHelper { - public static string CreateId( - string idNamespace, - string idName, - ParentClass? parentClass, - string template) - => CreateId(idNamespace, idName, parentClass, template, null); - public static string CreateId( string idNamespace, string idName, ParentClass? parentClass, string template, + bool addDefaultAttributes, StringBuilder? sb) { if (string.IsNullOrEmpty(idName)) @@ -68,7 +62,7 @@ public static string CreateId( parentClass = parent.Child; } - if (!hasGenericParent) + if (addDefaultAttributes && !hasGenericParent) { sb.AppendLine(" [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))]"); sb.AppendLine(" [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))]"); diff --git a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs index bdafcd3f8..aeee5897f 100644 --- a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs +++ b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs @@ -54,17 +54,17 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.RegisterSourceOutput( structAndDiagnostics.SelectMany((x, _) => x.Errors), - static (context, info) => context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location))); + static (context, info) => context.ReportDiagnostic(info)); context.RegisterSourceOutput( defaultsAndDiagnostics.SelectMany((x, _) => x.Errors), - static (context, info) => context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location))); + static (context, info) => context.ReportDiagnostic(info)); IncrementalValuesProvider structs = structAndDiagnostics .Where(static x => x.Value.valid) .Select((result, _) => result.Value.info); - IncrementalValueProvider<(string? Content, bool isValid, DiagnosticInfo? Diagnostic)> defaultTemplateContent = defaultsAndDiagnostics + IncrementalValueProvider<(string? Content, bool isValid, bool IsBuiltIn, DiagnosticInfo? Diagnostic)> defaultTemplateContent = defaultsAndDiagnostics .Where(static x => x.Value.valid) .Select((result, _) => result.Value.defaults) .Collect() @@ -74,27 +74,27 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (all.Left.IsDefaultOrEmpty) { // no default attributes, valid, but no content - return (null, true, null); + return (null, true, true, null); } // technically we can never have more than one `Defaults` here // but check for it just in case if (all.Left is {IsDefaultOrEmpty: false, Length: > 1}) { - return (null, false, null); + return (null, false, true, null); } var defaults = all.Left[0]; if (defaults.HasMultiple) { // not valid - return (null, false, null); + return (null, false, true, null); } if (defaults.Template is { } templateId) { // Explicit template - return (EmbeddedSources.GetTemplate(templateId), true, (DiagnosticInfo?) null); + return (EmbeddedSources.GetTemplate(templateId), true, true, (DiagnosticInfo?) null); } // We have already checked for a null template name and flagged it as an error @@ -106,16 +106,16 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (string.Equals(templateDetails.Name, defaultsTemplateName, StringComparison.Ordinal)) { // This _could_ be empty, but we use it anyway (and add a comment in the template) - return (templateDetails.Content ?? GetEmptyTemplateContent(defaultsTemplateName!), true, null); + return (templateDetails.Content ?? GetEmptyTemplateContent(defaultsTemplateName!), true, false, null); } } // Template name specified, but we don't have a template for it - return (null, false, UnknownTemplateDiagnostic.CreateInfo(defaults!.TemplateLocation!, defaultsTemplateName!)); + return (null, false, true, UnknownTemplateDiagnostic.CreateInfo(defaults.TemplateLocation!, defaultsTemplateName!)); } // only get here if the template name was null/empty, which is already reported - return (null, false, null); + return (null, false, true, null); }); var structsWithDefaultsAndTemplates = structs @@ -129,17 +129,17 @@ public void Initialize(IncrementalGeneratorInitializationContext context) private static void Execute( StructToGenerate idToGenerate, ImmutableArray<(string Path, string Name, string? Content)> templates, - (string? Content, bool IsValid, DiagnosticInfo? Diagnostics) defaults, + (string? Content, bool IsValid, bool IsBuiltInTemplate, DiagnosticInfo? Diagnostics) defaults, SourceProductionContext context) { var sb = new StringBuilder(); if (defaults.Diagnostics is { } diagnostic) { // report error with the default template - context.ReportDiagnostic(Diagnostic.Create(diagnostic.Descriptor, diagnostic.Location)); + context.ReportDiagnostic(diagnostic); } - if (!TryGetTemplateContent(idToGenerate, templates, defaults.IsValid, defaults.Content, context, out var templateContent)) + if (!TryGetTemplateContent(idToGenerate, templates, defaults, in context, out var templateContent, out var addDefaultAttributes)) { return; } @@ -149,6 +149,7 @@ private static void Execute( idToGenerate.Name, idToGenerate.Parent, templateContent, + addDefaultAttributes, sb); var fileName = SourceGenerationHelper.CreateSourceName( @@ -161,15 +162,16 @@ private static void Execute( private static bool TryGetTemplateContent( in StructToGenerate idToGenerate, in ImmutableArray<(string Path, string Name, string? Content)> templates, - bool haveValidDefault, - string? defaultContent, + (string? Content, bool IsValid, bool IsBuiltInTemplate, DiagnosticInfo? Diagnostics) defaults, in SourceProductionContext context, - [NotNullWhen(true)] out string? templateContent) + [NotNullWhen(true)] out string? templateContent, + out bool addDefaultAttributes) { // built-in template specified if (idToGenerate.Template is { } templateId) { templateContent = EmbeddedSources.GetTemplate(templateId); + addDefaultAttributes = true; return true; } @@ -181,25 +183,38 @@ private static bool TryGetTemplateContent( if (string.Equals(templateDetails.Name, idToGenerate.TemplateName, StringComparison.Ordinal)) { templateContent = templateDetails.Content ?? GetEmptyTemplateContent(idToGenerate.TemplateName!); + addDefaultAttributes = false; return true; } } // the template wasn't found, so it must be invalid. Don't generate anything var info = UnknownTemplateDiagnostic.CreateInfo(idToGenerate.TemplateLocation!, idToGenerate.TemplateName!); - context.ReportDiagnostic(Diagnostic.Create(info.Descriptor, info.Location)); + context.ReportDiagnostic(info); templateContent = null; + addDefaultAttributes = false; return false; } // nothing specified, use the default (if we have one) - if (haveValidDefault) + if (defaults.IsValid) { - templateContent = defaultContent ?? EmbeddedSources.GetTemplate(Template.Guid); + if (defaults.Content is { } content) + { + templateContent = content; + addDefaultAttributes = defaults.IsBuiltInTemplate; + } + else + { + templateContent = EmbeddedSources.GetTemplate(Template.Guid); + addDefaultAttributes = true; + } + return true; } templateContent = null; + addDefaultAttributes = true; return false; } diff --git a/src/StronglyTypedIds/Templates/guid-full.typedid b/src/StronglyTypedIds/Templates/guid-full.typedid index 6feacc938..61fe33264 100644 --- a/src/StronglyTypedIds/Templates/guid-full.typedid +++ b/src/StronglyTypedIds/Templates/guid-full.typedid @@ -1,3 +1,5 @@ + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID : #if NET6_0_OR_GREATER diff --git a/src/StronglyTypedIds/Templates/int-full.typedid b/src/StronglyTypedIds/Templates/int-full.typedid index 100d38f25..b2208465b 100644 --- a/src/StronglyTypedIds/Templates/int-full.typedid +++ b/src/StronglyTypedIds/Templates/int-full.typedid @@ -1,3 +1,5 @@ + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID : #if NET6_0_OR_GREATER diff --git a/src/StronglyTypedIds/Templates/long-full.typedid b/src/StronglyTypedIds/Templates/long-full.typedid index 33e71cebc..78447edfe 100644 --- a/src/StronglyTypedIds/Templates/long-full.typedid +++ b/src/StronglyTypedIds/Templates/long-full.typedid @@ -1,3 +1,5 @@ + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID : #if NET6_0_OR_GREATER diff --git a/src/StronglyTypedIds/Templates/newid-full.typedid b/src/StronglyTypedIds/Templates/newid-full.typedid index 76d6ca699..779baef92 100644 --- a/src/StronglyTypedIds/Templates/newid-full.typedid +++ b/src/StronglyTypedIds/Templates/newid-full.typedid @@ -1,3 +1,5 @@ + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID : #if NET6_0_OR_GREATER diff --git a/src/StronglyTypedIds/Templates/nullablestring-full.typedid b/src/StronglyTypedIds/Templates/nullablestring-full.typedid index 6a2ede966..2c86980fa 100644 --- a/src/StronglyTypedIds/Templates/nullablestring-full.typedid +++ b/src/StronglyTypedIds/Templates/nullablestring-full.typedid @@ -1,3 +1,5 @@ + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID : #if NET6_0_OR_GREATER diff --git a/src/StronglyTypedIds/Templates/string-full.typedid b/src/StronglyTypedIds/Templates/string-full.typedid index f04dbab67..bdb3b9195 100644 --- a/src/StronglyTypedIds/Templates/string-full.typedid +++ b/src/StronglyTypedIds/Templates/string-full.typedid @@ -1,3 +1,5 @@ + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID : #if NET6_0_OR_GREATER From 3b9135919154071ce3f5234c97d141ba4406d31f Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sun, 5 Nov 2023 22:52:54 +0000 Subject: [PATCH 16/47] Add codefixprovider (need to try it) --- .../UnknownTemplateCodeFixProvider.cs | 125 +++++++++ src/StronglyTypedIds/EmbeddedSources.cs | 5 +- src/StronglyTypedIds/StronglyTypedIds.csproj | 4 +- ...sts.UsesBuiltInTemplates_Guid.verified.txt | 264 ++++++++++++++++++ ...ests.UsesBuiltInTemplates_Int.verified.txt | 260 +++++++++++++++++ ...sts.UsesBuiltInTemplates_Long.verified.txt | 261 +++++++++++++++++ ...s.UsesBuiltInTemplates_String.verified.txt | 253 +++++++++++++++++ 7 files changed, 1170 insertions(+), 2 deletions(-) create mode 100644 src/StronglyTypedIds/Diagnostics/UnknownTemplateCodeFixProvider.cs create mode 100644 test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt diff --git a/src/StronglyTypedIds/Diagnostics/UnknownTemplateCodeFixProvider.cs b/src/StronglyTypedIds/Diagnostics/UnknownTemplateCodeFixProvider.cs new file mode 100644 index 000000000..fa42a632a --- /dev/null +++ b/src/StronglyTypedIds/Diagnostics/UnknownTemplateCodeFixProvider.cs @@ -0,0 +1,125 @@ +// Based on https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/1dd5ced072d7d870f6dd698a6c02ad509a122452/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Settings/UnknownTemplateCodeFixProvider.cs + +#nullable disable + +using System; +using System.Collections.Immutable; +using System.Composition; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; + +namespace StronglyTypedIds.Diagnostics; + +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(UnknownTemplateCodeFixProvider)), Shared] +internal class UnknownTemplateCodeFixProvider : CodeFixProvider +{ + internal const string DefaultHeader = + """" + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See + // https://github.com/dotnet/roslyn/issues/4655 for more details. + // + // To enable the template, in Visual Studio 2017, 2019, and 2022: + // 1. Select the file in Solution Explorer. + // 2. In the 'Properties' window, set the value for 'Build Action' + // to one of the following (whichever is available): + // - For .NET Core and .NET Standard projects: 'C# analyzer additional file' + // - For other projects: 'AdditionalFiles' + // + // Any instances of PLACEHOLDERID will be replaced with the target ID name + // when generating code from this template. + + + """"; + + /// + public override ImmutableArray FixableDiagnosticIds { get; } = + ImmutableArray.Create(Diagnostics.UnknownTemplateDiagnostic.Id); + + /// + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + var project = context.Document.Project; + var workspace = project.Solution.Workspace; + + // if we can't add extra documents, there's nothing we can do + if (!workspace.CanApplyChange(ApplyChangesKind.AddAdditionalDocument)) + { + return Task.CompletedTask; + } + + foreach (var diagnostic in context.Diagnostics) + { + if(!diagnostic.Properties.TryGetValue(UnknownTemplateDiagnostic.TemplateName, out var templateName)) + { + // This shouldn't happen, but play it safe + continue; + } + + // check if the template file already exists + var alreadyAdded = false; + foreach (var document in project.AdditionalDocuments) + { + if (document.Name.Equals(templateName, StringComparison.OrdinalIgnoreCase)) + { + alreadyAdded = true; + break; + } + } + + if (alreadyAdded) + { + continue; + } + + context.RegisterCodeFix( + CodeAction.Create( + $"Add {templateName}.typedid template to the project", + cancellationToken => GetTransformedSolutionAsync(context.Document, templateName, cancellationToken), + nameof(UnknownTemplateCodeFixProvider)), + diagnostic); + } + + return Task.CompletedTask; + } + + /// + public override FixAllProvider GetFixAllProvider() + { + // This code fix does not support fix all actions. + return null; + } + + private static Task GetTransformedSolutionAsync(Document document, string templateName, CancellationToken cancellationToken) + { + // Currently unused + _ = cancellationToken; + + var project = document.Project; + var solution = project.Solution; + + var newDocumentId = DocumentId.CreateNewId(project.Id); + + var templateContent = GetTemplateContent(templateName); + + var newSolution = solution.AddAdditionalDocument(newDocumentId, $"{templateName}.typedid", templateContent); + + return Task.FromResult(newSolution); + } + + internal static string GetTemplateContent(string templateName) + { + var templateContent = templateName switch + { + { } x when x.Contains("int", StringComparison.OrdinalIgnoreCase) => EmbeddedSources.LoadEmbeddedTypedId("int-full.typedid"), + { } x when x.Contains("long", StringComparison.OrdinalIgnoreCase) => EmbeddedSources.LoadEmbeddedTypedId("long-full.typedid"), + { } x when x.Contains("string", StringComparison.OrdinalIgnoreCase) => EmbeddedSources.LoadEmbeddedTypedId("string-full.typedid"), + _ => EmbeddedSources.LoadEmbeddedTypedId("guid-full.typedid"), + }; + + return DefaultHeader + templateContent; + } +} \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.cs b/src/StronglyTypedIds/EmbeddedSources.cs index 41b940483..33a947c10 100644 --- a/src/StronglyTypedIds/EmbeddedSources.cs +++ b/src/StronglyTypedIds/EmbeddedSources.cs @@ -24,7 +24,10 @@ internal static string GetTemplate(Template template) Template.NullableString => NullableStringTemplate, _ => string.Empty, }; - + + internal static string LoadEmbeddedTypedId(string templateName) + => LoadEmbeddedResource($"StronglyTypedIds.Templates.{templateName}"); + internal static string LoadEmbeddedResource(string resourceName) { var resourceStream = ThisAssembly.GetManifestResourceStream(resourceName); diff --git a/src/StronglyTypedIds/StronglyTypedIds.csproj b/src/StronglyTypedIds/StronglyTypedIds.csproj index ac155cec1..5117fdd09 100644 --- a/src/StronglyTypedIds/StronglyTypedIds.csproj +++ b/src/StronglyTypedIds/StronglyTypedIds.csproj @@ -12,6 +12,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -20,10 +21,11 @@ + + - diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt new file mode 100644 index 000000000..9860d9b22 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt @@ -0,0 +1,264 @@ +// ACTION REQUIRED: This file was automatically added to your project, but it +// will not take effect until additional steps are taken to enable it. See +// https://github.com/dotnet/roslyn/issues/4655 for more details. +// +// To enable the template, in Visual Studio 2017, 2019, and 2022: +// 1. Select the file in Solution Explorer. +// 2. In the 'Properties' window, set the value for 'Build Action' +// to one of the following (whichever is available): +// - For .NET Core and .NET Standard projects: 'C# analyzer additional file' +// - For other projects: 'AdditionalFiles' +// +// Any instances of PLACEHOLDERID will be replaced with the target ID name +// when generating code from this template. + + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public PLACEHOLDERID(global::System.Guid value) + { + Value = value; + } + + public static PLACEHOLDERID New() => new PLACEHOLDERID(global::System.Guid.NewGuid()); + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(global::System.Guid.Empty); + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new PLACEHOLDERID(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null"))); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + global::System.Guid guidValue => new PLACEHOLDERID(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var guid = serializer.Deserialize(reader); + return guid.HasValue ? new PLACEHOLDERID(guid.Value) : null; + } + } + } \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt new file mode 100644 index 000000000..4998abd15 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt @@ -0,0 +1,260 @@ +// ACTION REQUIRED: This file was automatically added to your project, but it +// will not take effect until additional steps are taken to enable it. See +// https://github.com/dotnet/roslyn/issues/4655 for more details. +// +// To enable the template, in Visual Studio 2017, 2019, and 2022: +// 1. Select the file in Solution Explorer. +// 2. In the 'Properties' window, set the value for 'Build Action' +// to one of the following (whichever is available): +// - For .NET Core and .NET Standard projects: 'C# analyzer additional file' +// - For other projects: 'AdditionalFiles' +// +// Any instances of PLACEHOLDERID will be replaced with the target ID name +// when generating code from this template. + + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public int Value { get; } + + public PLACEHOLDERID(int value) + { + Value = value; + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(0); + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + int intValue => new PLACEHOLDERID(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(int) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(int)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(int.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null"))); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(int.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(int.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (int.TryParse(input, provider, out var value)) + { + result = new(value); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(int.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(int.Parse(input, provider)); +#else + => new(int.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { +#if NET7_0_OR_GREATER + if (int.TryParse(input, provider, out var guid)) +#else + if (int.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + int intValue => new PLACEHOLDERID(intValue), + long longValue when longValue < int.MaxValue => new PLACEHOLDERID((int)longValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var result = serializer.Deserialize(reader); + return result.HasValue ? new PLACEHOLDERID(result.Value) : null; + } + } + } \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt new file mode 100644 index 000000000..be319d4a3 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt @@ -0,0 +1,261 @@ +// ACTION REQUIRED: This file was automatically added to your project, but it +// will not take effect until additional steps are taken to enable it. See +// https://github.com/dotnet/roslyn/issues/4655 for more details. +// +// To enable the template, in Visual Studio 2017, 2019, and 2022: +// 1. Select the file in Solution Explorer. +// 2. In the 'Properties' window, set the value for 'Build Action' +// to one of the following (whichever is available): +// - For .NET Core and .NET Standard projects: 'C# analyzer additional file' +// - For other projects: 'AdditionalFiles' +// +// Any instances of PLACEHOLDERID will be replaced with the target ID name +// when generating code from this template. + + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public long Value { get; } + + public PLACEHOLDERID(long value) + { + Value = value; + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(0); + + /// + public bool Equals(PLACEHOLDERID other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + long intValue => new PLACEHOLDERID(intValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(long) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(long)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(long) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetInt32()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteNumberValue(value.Value); + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(long.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null"))); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString(global::System.Globalization.CultureInfo.InvariantCulture)); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(long.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(long.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + if (long.TryParse(input, provider, out var value)) + { + result = new(value); + return true; + } + + result = default; + return false; + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(long.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(long.Parse(input, provider)); +#else + => new(long.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { +#if NET7_0_OR_GREATER + if (long.TryParse(input, provider, out var guid)) +#else + if (long.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + + result = default; + return false; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + long longValue => new PLACEHOLDERID(longValue), + int intValue => new PLACEHOLDERID(intValue), + short shortValue => new PLACEHOLDERID(shortValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var result = serializer.Deserialize(reader); + return result.HasValue ? new PLACEHOLDERID(result.Value) : null; + } + } + } \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt new file mode 100644 index 000000000..a470653ea --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt @@ -0,0 +1,253 @@ +// ACTION REQUIRED: This file was automatically added to your project, but it +// will not take effect until additional steps are taken to enable it. See +// https://github.com/dotnet/roslyn/issues/4655 for more details. +// +// To enable the template, in Visual Studio 2017, 2019, and 2022: +// 1. Select the file in Solution Explorer. +// 2. In the 'Properties' window, set the value for 'Build Action' +// to one of the following (whichever is available): +// - For .NET Core and .NET Standard projects: 'C# analyzer additional file' +// - For other projects: 'AdditionalFiles' +// +// Any instances of PLACEHOLDERID will be replaced with the target ID name +// when generating code from this template. + + [global::System.ComponentModel.TypeConverter(typeof(PLACEHOLDERIDTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(PLACEHOLDERIDSystemTextJsonConverter))] + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public string Value { get; } + + public PLACEHOLDERID(string value) + { + Value = value ?? throw new global::System.ArgumentNullException(nameof(value)); + } + + public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(string.Empty); + + /// + public bool Equals(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => true, + (null, _) => false, + (_, null) => false, + (_, _) => Value.Equals(other.Value), + }; + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PLACEHOLDERID other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value; + + public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); + public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + + /// + public int CompareTo(PLACEHOLDERID other) + => (Value, other.Value) switch + { + (null, null) => 0, + (null, _) => -1, + (_, null) => 1, + (_, _) => Value.CompareTo(other.Value), + }; + + class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + if (value is string stringValue) + { + return new PLACEHOLDERID(stringValue); + } + + return base.ConvertFrom(context, culture, value); + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is PLACEHOLDERID idValue) + { + if (destinationType == typeof(string)) + { + return idValue.Value; + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetString()!); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(reader.GetString() ?? throw new global::System.FormatException("The string for the PLACEHOLDERID property was null")); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value); +#endif + } + + public static PLACEHOLDERID Parse(string input) + => new(input); + +#if NET7_0_OR_GREATER + /// + public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) + => new(input); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out PLACEHOLDERID result) + { + if (input is null) + { + result = default; + return false; + } + + result = new(input); + return true; + } +#endif + + /// + public string ToString(string? format, global::System.IFormatProvider? formatProvider) + => Value; + +#if NETCOREAPP2_1_OR_GREATER + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) + => new(input.ToString()); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) + => new(input.ToString()); + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) + { + result = new(input.ToString()); + return true; + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, + global::System.ReadOnlySpan format = default) + { + if (destination.Length > Value.Length) + { + global::System.MemoryExtensions.AsSpan(Value).CopyTo(destination); + charsWritten = Value.Length; + return true; + } + + charsWritten = default; + return false; + } +#endif + + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + string stringValue => new PLACEHOLDERID(stringValue), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + if (objectType == typeof(PLACEHOLDERID?)) + { + var value = serializer.Deserialize(reader); + + return value is null ? null : new PLACEHOLDERID(value); + } + + return new PLACEHOLDERID(serializer.Deserialize(reader)!); + } + } + } \ No newline at end of file From 6d71ccb4e4c6442424a1a6d0d985324eee13a57e Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sun, 5 Nov 2023 22:57:11 +0000 Subject: [PATCH 17/47] Fix nullability warning --- src/StronglyTypedIds/StronglyTypedIdGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs index aeee5897f..1603fa51b 100644 --- a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs +++ b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs @@ -94,7 +94,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (defaults.Template is { } templateId) { // Explicit template - return (EmbeddedSources.GetTemplate(templateId), true, true, (DiagnosticInfo?) null); + return ((string?) EmbeddedSources.GetTemplate(templateId), true, true, (DiagnosticInfo?) null); } // We have already checked for a null template name and flagged it as an error From bd8ea0c6a6767462bd6e258443c9dd2f048c8ef9 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Mon, 6 Nov 2023 21:45:09 +0000 Subject: [PATCH 18/47] Make the analyzer return an error instead --- .../Diagnostics/InvalidTemplateNameDiagnostic.cs | 8 +------- .../Diagnostics/UnknownTemplateDiagnostic.cs | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs index f24e6f047..2997eeea1 100644 --- a/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs @@ -8,14 +8,8 @@ internal static class InvalidTemplateNameDiagnostic internal const string Message = "The template name must not be null or whitespace."; internal const string Title = "Invalid template name"; - public static Diagnostic Create(SyntaxNode currentNode) => - Diagnostic.Create( - new DiagnosticDescriptor( - Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), - currentNode.GetLocation()); - public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) => new(new DiagnosticDescriptor( - Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), + Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true), currentNode.GetLocation()); } \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs index 6fc3a501d..d836e37c5 100644 --- a/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs @@ -16,6 +16,6 @@ public static DiagnosticInfo CreateInfo(LocationInfo location, string name) public static DiagnosticDescriptor CreateDescriptor() => new( - Id, Title, "Could not find '{0}.typedid' template. Ensure the template exists and has a build action of 'Additional Files'.", - category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true); + Id, Title, "Could not find '{0}.typedid' template. Ensure the template exists in the project and has a build action of 'Additional Files'.", + category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true); } \ No newline at end of file From 50df02a6d73d0d1a01ebdc32f33af58a38cf9980 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Mon, 6 Nov 2023 21:51:05 +0000 Subject: [PATCH 19/47] Revert accidental hacking aroudn --- build/Build.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Build.cs b/build/Build.cs index aa78772cd..39bb2c919 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -116,7 +116,7 @@ class Build : NukeBuild var projectFiles = new[] { TestsDirectory / "StronglyTypedIds.Nuget.IntegrationTests", - // TestsDirectory / "StronglyTypedIds.Nuget.Attributes.IntegrationTests", + TestsDirectory / "StronglyTypedIds.Nuget.Attributes.IntegrationTests", }; if (!string.IsNullOrEmpty(PackagesDirectory)) From f878a23ecc185933e0abade9918e07b336c61f2a Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Mon, 6 Nov 2023 22:23:22 +0000 Subject: [PATCH 20/47] Make nullable ID an extended type --- src/StronglyTypedIds.Attributes/Template.cs | 1 - .../EmbeddedSources.NullableString.cs | 191 ------------------ src/StronglyTypedIds/EmbeddedSources.cs | 1 - .../DapperTypeHandlers.cs | 2 +- .../Enums.cs | 5 +- .../NullableStringIdTests.cs | 46 ++--- ...ledResource_resource=Template.verified.txt | 1 - .../Snapshots/NoGeneratedIds.verified.txt | 1 - ...ateDefaultIdInGlobalNamespace.verified.txt | 1 - ....CanGenerateForCustomTemplate.verified.txt | 1 - ...yNestedIdInFileScopeNamespace.verified.txt | 1 - ...nerateIdInFileScopedNamespace.verified.txt | 1 - ...ests.CanGenerateIdInNamespace.verified.txt | 1 - ...nerateMultipleIdsWithSameName.verified.txt | 1 - ...eNestedIdInFileScopeNamespace.verified.txt | 1 - ...nerateNonDefaultIdInNamespace.verified.txt | 1 - ...yNestedIdInFileScopeNamespace.verified.txt | 1 - ...mTemplateUsingGlobalAttribute.verified.txt | 1 - ...hTemplateUsingGlobalAttribute.verified.txt | 1 - 19 files changed, 25 insertions(+), 234 deletions(-) delete mode 100644 src/StronglyTypedIds/EmbeddedSources.NullableString.cs diff --git a/src/StronglyTypedIds.Attributes/Template.cs b/src/StronglyTypedIds.Attributes/Template.cs index 6ec5e9473..3ac8cfa8a 100644 --- a/src/StronglyTypedIds.Attributes/Template.cs +++ b/src/StronglyTypedIds.Attributes/Template.cs @@ -24,6 +24,5 @@ public enum Template Int, String, Long, - NullableString, } } \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.NullableString.cs b/src/StronglyTypedIds/EmbeddedSources.NullableString.cs deleted file mode 100644 index b234a523b..000000000 --- a/src/StronglyTypedIds/EmbeddedSources.NullableString.cs +++ /dev/null @@ -1,191 +0,0 @@ -namespace StronglyTypedIds; - -internal static partial class EmbeddedSources -{ - private const string NullableStringTemplate = """ - partial struct PLACEHOLDERID : - #if NET6_0_OR_GREATER - global::System.ISpanFormattable, - #endif - #if NET7_0_OR_GREATER - global::System.IParsable, global::System.ISpanParsable, - #endif - global::System.IComparable, global::System.IEquatable, global::System.IFormattable - { - public string? Value { get; } - - public PLACEHOLDERID(string? value) - { - Value = value; - } - - public static readonly PLACEHOLDERID Empty = new PLACEHOLDERID(string.Empty); - - /// - public bool Equals(PLACEHOLDERID other) - => (Value, other.Value) switch - { - (null, null) => true, - (null, _) => false, - (_, null) => false, - (_, _) => Value.Equals(other.Value), - }; - - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is PLACEHOLDERID other && Equals(other); - } - - public override int GetHashCode() => Value?.GetHashCode() ?? 0; - - public override string? ToString() => Value; - - public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); - public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - - /// - public int CompareTo(PLACEHOLDERID other) - => (Value, other.Value) switch - { - (null, null) => 0, - (null, _) => -1, - (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), - }; - - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter - { - public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) - => value switch - { - null => new PLACEHOLDERID(null), - string x => new PLACEHOLDERID(x), - _ => base.ConvertFrom(context, culture, value), - }; - - public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) - { - return sourceType == typeof(string) || base.CanConvertTo(context, sourceType); - } - - public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) - { - if (value is PLACEHOLDERID idValue) - { - if (destinationType == typeof(string)) - { - return idValue.Value; - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter - { - public override bool CanConvert(global::System.Type typeToConvert) - => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); - - public override PLACEHOLDERID Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new (reader.GetString()); - - public override void Write(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) - { - if (value.Value is null) - { - writer.WriteNullValue(); - } - else - { - writer.WriteStringValue(value.Value); - } - } - - #if NET6_0_OR_GREATER - public override PLACEHOLDERID ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) - => new(reader.GetString()); - - public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, PLACEHOLDERID value, global::System.Text.Json.JsonSerializerOptions options) - => writer.WritePropertyName(value.Value ?? string.Empty); - #endif - } - - public static PLACEHOLDERID Parse(string input) - => new(input); - - #if NET7_0_OR_GREATER - /// - public static PLACEHOLDERID Parse(string input, global::System.IFormatProvider? provider) - => new(input); - - /// - public static bool TryParse( - string? input, - global::System.IFormatProvider? provider, - out PLACEHOLDERID result) - { - result = new(input); - return true; - } - #endif - - /// - public string ToString(string? format, global::System.IFormatProvider? formatProvider) - => Value ?? string.Empty; - - #if NETCOREAPP2_1_OR_GREATER - public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input) - => new(input.ToString()); - #endif - - #if NET6_0_OR_GREATER - #if NET7_0_OR_GREATER - /// - #endif - public static PLACEHOLDERID Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) - => new(input.ToString()); - - #if NET7_0_OR_GREATER - /// - #endif - public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out PLACEHOLDERID result) - { - result = new(input.ToString()); - return true; - } - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, - global::System.ReadOnlySpan format, - global::System.IFormatProvider? provider) - => TryFormat(destination, out charsWritten, format); - - /// - public bool TryFormat( - global::System.Span destination, - out int charsWritten, - global::System.ReadOnlySpan format = default) - { - if (Value is not null && destination.Length > Value.Length) - { - global::System.MemoryExtensions.AsSpan(Value).CopyTo(destination); - charsWritten = Value.Length; - return true; - } - - charsWritten = default; - return false; - } - #endif - } - """; -} \ No newline at end of file diff --git a/src/StronglyTypedIds/EmbeddedSources.cs b/src/StronglyTypedIds/EmbeddedSources.cs index 33a947c10..e54f812ab 100644 --- a/src/StronglyTypedIds/EmbeddedSources.cs +++ b/src/StronglyTypedIds/EmbeddedSources.cs @@ -21,7 +21,6 @@ internal static string GetTemplate(Template template) Template.Int => IntTemplate, Template.Long => LongTemplate, Template.String => StringTemplate, - Template.NullableString => NullableStringTemplate, _ => string.Empty, }; diff --git a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs index 3c9f7b0c2..a223b2f0e 100644 --- a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs +++ b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs @@ -13,7 +13,7 @@ public static void AddHandlers() SqlMapper.AddTypeHandler(new ConvertersIntId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersLongId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersStringId.DapperTypeHandler()); - SqlMapper.AddTypeHandler(new ConvertersNullableStringId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new NullableStringId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new NewIdId1.DapperTypeHandler()); } } diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index 12d0d7525..6c4c1f1c9 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -60,11 +60,8 @@ public bool TryFormat2( [StronglyTypedId("string-full")] partial struct ConvertersStringId { } -[StronglyTypedId(Template.NullableString)] -partial struct NullableStringId { } - [StronglyTypedId("nullablestring-full")] -partial struct ConvertersNullableStringId { } +partial struct NullableStringId { } public partial class SomeType where T : new() { diff --git a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs index 58f943cb7..6264bbcb8 100644 --- a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs @@ -69,7 +69,7 @@ public void DifferentTypesAreUnequal() [Fact] public void CanSerializeToString_WithNewtonsoftJsonProvider() { - var foo = new ConvertersNullableStringId("123"); + var foo = new NullableStringId("123"); var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); @@ -94,7 +94,7 @@ public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() [Fact] public void CanSerializeToString_WithSystemTextJsonProvider() { - var foo = new ConvertersNullableStringId("123"); + var foo = new NullableStringId("123"); var serializedFoo = SystemTextJsonSerializer.Serialize(foo); var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); @@ -140,10 +140,10 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() public void CanDeserializeFromString_WithNewtonsoftJsonProvider() { var value = "123"; - var foo = new ConvertersNullableStringId(value); + var foo = new NullableStringId(value); var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); - var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); Assert.Equal(foo, deserializedFoo); } @@ -152,10 +152,10 @@ public void CanDeserializeFromString_WithNewtonsoftJsonProvider() public void CanDeserializeFromString_WithSystemTextJsonProvider() { var value = "123"; - var foo = new ConvertersNullableStringId(value); + var foo = new NullableStringId(value); var serializedString = SystemTextJsonSerializer.Serialize(value); - var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); Assert.Equal(foo, deserializedFoo); } @@ -163,7 +163,7 @@ public void CanDeserializeFromString_WithSystemTextJsonProvider() [Fact] public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() { - var foo = new ConvertersNullableStringId("123"); + var foo = new NullableStringId("123"); var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); @@ -182,7 +182,7 @@ public void WhenEfCoreValueConverterUsesValueConverter() .UseSqlite(connection) .Options; - var original = new TestEntity { Id = Guid.NewGuid(), Name = new ConvertersNullableStringId("some name") }; + var original = new TestEntity { Id = Guid.NewGuid(), Name = new NullableStringId("some name") }; using (var context = new TestDbContext(options)) { context.Database.EnsureCreated(); @@ -205,10 +205,10 @@ public async Task WhenDapperValueConverterUsesValueConverter() using var connection = new SqliteConnection("DataSource=:memory:"); await connection.OpenAsync(); - var results = await connection.QueryAsync("SELECT 'this is a value'"); + var results = await connection.QueryAsync("SELECT 'this is a value'"); var value = Assert.Single(results); - Assert.Equal(value, new ConvertersNullableStringId("this is a value")); + Assert.Equal(value, new NullableStringId("this is a value")); } [Theory] @@ -216,10 +216,10 @@ public async Task WhenDapperValueConverterUsesValueConverter() [InlineData("some value")] public void TypeConverter_CanConvertToAndFrom(object value) { - var converter = TypeDescriptor.GetConverter(typeof(ConvertersNullableStringId)); + var converter = TypeDescriptor.GetConverter(typeof(NullableStringId)); var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new ConvertersNullableStringId(value?.ToString()), id); + Assert.IsType(id); + Assert.Equal(new NullableStringId(value?.ToString()), id); var reconverted = converter.ConvertTo(id, value.GetType()); Assert.Equal(value, reconverted); @@ -320,7 +320,7 @@ public void NullHashCodes() public void NullSerializesAsExpectedWithConverters() { var expected = "null"; - var value = new ConvertersNullableStringId(null); + var value = new NullableStringId(null); var json = SystemTextJsonSerializer.Serialize(value); var systemText = SystemTextJsonSerializer.Serialize(value); @@ -331,10 +331,10 @@ public void NullSerializesAsExpectedWithConverters() [Fact] public void TypeConverterConvertsNullAsExpected() { - var converter = TypeDescriptor.GetConverter(typeof(ConvertersNullableStringId)); + var converter = TypeDescriptor.GetConverter(typeof(NullableStringId)); var id = converter.ConvertFrom(null); - Assert.IsType(id); - Assert.Equal(new ConvertersNullableStringId(null), id); + Assert.IsType(id); + Assert.Equal(new NullableStringId(null), id); var reconverted = converter.ConvertTo(id, typeof(string)); Assert.Null(reconverted); @@ -351,7 +351,7 @@ public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() .UseSqlite(connection) .Options; - var original = new TestEntity { Id = Guid.NewGuid(), Name = new ConvertersNullableStringId("some name") }; + var original = new TestEntity { Id = Guid.NewGuid(), Name = new NullableStringId("some name") }; using (var context = new ConventionsDbContext(options)) { context.Database.EnsureCreated(); @@ -379,8 +379,8 @@ public ConventionsDbContext(DbContextOptions options) : base(options) protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { configurationBuilder - .Properties() - .HaveConversion(); + .Properties() + .HaveConversion(); } protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -411,7 +411,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { builder .Property(x => x.Name) - .HasConversion(new ConvertersNullableStringId.EfCoreValueConverter()) + .HasConversion(new NullableStringId.EfCoreValueConverter()) .ValueGeneratedNever(); }); } @@ -420,13 +420,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) internal class TestEntity { public Guid Id { get; set; } - public ConvertersNullableStringId Name { get; set; } + public NullableStringId Name { get; set; } } internal class EntityWithNullableId { - public ConvertersNullableStringId? Id { get; set; } + public NullableStringId? Id { get; set; } } internal class TypeWithDictionaryKeys diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt index 3e75e0b60..9de4588cf 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=Template.verified.txt @@ -26,7 +26,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt index de5f8b4ce..65833f742 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index 04263eb00..aab895549 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt index 6b5774e63..cf6565528 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt index 0b0d55e7c..875dc81f1 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index a77d44032..9ca113834 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index a77d44032..9ca113834 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 320b793f7..2e0fa5643 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index c7a59d47e..18be5df5c 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index 631b00ff2..54d2abebc 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index 0249d27de..a7064e440 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt index 6b2725b74..7133d9a9a 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index 3aea33e05..325b12247 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -148,7 +148,6 @@ namespace StronglyTypedIds Int, String, Long, - NullableString, } } #endif From 1505a3c10bb8a2c28152d34981c6ea9f7b952d9c Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Tue, 7 Nov 2023 20:26:19 +0000 Subject: [PATCH 21/47] Move to separate templates NuGet folder --- .gitignore | 3 +++ NuGet.integration-tests.config | 12 +++++++++ StronglyTypedId.sln | 15 +++++++++++ .../StronglyTypedId.Templates.targets} | 0 .../StronglyTypedIds.Templates.csproj | 25 +++++++++++++++++++ .../guid-full.typedid | 0 .../int-full.typedid | 0 .../long-full.typedid | 0 .../newid-full.typedid | 0 .../nullablestring-full.typedid | 0 .../string-full.typedid | 0 src/StronglyTypedIds/StronglyTypedIds.csproj | 10 +++----- .../StronglyTypedIds.IntegrationTests.csproj | 2 +- ...s.Nuget.Attributes.IntegrationTests.csproj | 1 + ...nglyTypedIds.Nuget.IntegrationTests.csproj | 1 + 15 files changed, 62 insertions(+), 7 deletions(-) rename src/{StronglyTypedIds/StronglyTypedId.targets => StronglyTypedIds.Templates/StronglyTypedId.Templates.targets} (100%) create mode 100644 src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj rename src/{StronglyTypedIds/Templates => StronglyTypedIds.Templates}/guid-full.typedid (100%) rename src/{StronglyTypedIds/Templates => StronglyTypedIds.Templates}/int-full.typedid (100%) rename src/{StronglyTypedIds/Templates => StronglyTypedIds.Templates}/long-full.typedid (100%) rename src/{StronglyTypedIds/Templates => StronglyTypedIds.Templates}/newid-full.typedid (100%) rename src/{StronglyTypedIds/Templates => StronglyTypedIds.Templates}/nullablestring-full.typedid (100%) rename src/{StronglyTypedIds/Templates => StronglyTypedIds.Templates}/string-full.typedid (100%) diff --git a/.gitignore b/.gitignore index d662c941d..71494e00d 100644 --- a/.gitignore +++ b/.gitignore @@ -245,3 +245,6 @@ ModelManifest.xml .fake/ tools/* !tools/packages.config + +# NuGet testing +globalPackagesFolder \ No newline at end of file diff --git a/NuGet.integration-tests.config b/NuGet.integration-tests.config index 59eaf0656..c71f27319 100644 --- a/NuGet.integration-tests.config +++ b/NuGet.integration-tests.config @@ -1,8 +1,20 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/StronglyTypedId.sln b/StronglyTypedId.sln index cd44309c6..036d076bd 100644 --- a/StronglyTypedId.sln +++ b/StronglyTypedId.sln @@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Nuget.Inte EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Nuget.Attributes.IntegrationTests", "test\StronglyTypedIds.Nuget.Attributes.IntegrationTests\StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj", "{19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Templates", "src\StronglyTypedIds.Templates\StronglyTypedIds.Templates.csproj", "{336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -104,6 +106,18 @@ Global {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}.Release|Any CPU.ActiveCfg = Release|Any CPU {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}.Release|x64.ActiveCfg = Release|Any CPU {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23}.Release|x86.ActiveCfg = Release|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Debug|x64.ActiveCfg = Debug|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Debug|x64.Build.0 = Debug|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Debug|x86.ActiveCfg = Debug|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Debug|x86.Build.0 = Debug|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Release|Any CPU.Build.0 = Release|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Release|x64.ActiveCfg = Release|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Release|x64.Build.0 = Release|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Release|x86.ActiveCfg = Release|Any CPU + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -115,6 +129,7 @@ Global {F25F6E67-E62A-4075-86CF-4C4EDD7E4883} = {EE1258BD-3422-4F55-B9CF-B4D6C95DAD68} {A7355210-7DDC-4968-84B7-79002113EA6E} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} + {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C} = {EE1258BD-3422-4F55-B9CF-B4D6C95DAD68} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8D1F0534-B8AD-4CFA-9C14-CBC757BCB1E1} diff --git a/src/StronglyTypedIds/StronglyTypedId.targets b/src/StronglyTypedIds.Templates/StronglyTypedId.Templates.targets similarity index 100% rename from src/StronglyTypedIds/StronglyTypedId.targets rename to src/StronglyTypedIds.Templates/StronglyTypedId.Templates.targets diff --git a/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj b/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj new file mode 100644 index 000000000..6571d9600 --- /dev/null +++ b/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj @@ -0,0 +1,25 @@ + + + + netstandard2.0 + false + enable + StronglyTypedId.Templates + A collection of templates for generating strongly-typed IDs by decorating with a [StronglyTypedId] attribute + latest + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/StronglyTypedIds/Templates/guid-full.typedid b/src/StronglyTypedIds.Templates/guid-full.typedid similarity index 100% rename from src/StronglyTypedIds/Templates/guid-full.typedid rename to src/StronglyTypedIds.Templates/guid-full.typedid diff --git a/src/StronglyTypedIds/Templates/int-full.typedid b/src/StronglyTypedIds.Templates/int-full.typedid similarity index 100% rename from src/StronglyTypedIds/Templates/int-full.typedid rename to src/StronglyTypedIds.Templates/int-full.typedid diff --git a/src/StronglyTypedIds/Templates/long-full.typedid b/src/StronglyTypedIds.Templates/long-full.typedid similarity index 100% rename from src/StronglyTypedIds/Templates/long-full.typedid rename to src/StronglyTypedIds.Templates/long-full.typedid diff --git a/src/StronglyTypedIds/Templates/newid-full.typedid b/src/StronglyTypedIds.Templates/newid-full.typedid similarity index 100% rename from src/StronglyTypedIds/Templates/newid-full.typedid rename to src/StronglyTypedIds.Templates/newid-full.typedid diff --git a/src/StronglyTypedIds/Templates/nullablestring-full.typedid b/src/StronglyTypedIds.Templates/nullablestring-full.typedid similarity index 100% rename from src/StronglyTypedIds/Templates/nullablestring-full.typedid rename to src/StronglyTypedIds.Templates/nullablestring-full.typedid diff --git a/src/StronglyTypedIds/Templates/string-full.typedid b/src/StronglyTypedIds.Templates/string-full.typedid similarity index 100% rename from src/StronglyTypedIds/Templates/string-full.typedid rename to src/StronglyTypedIds.Templates/string-full.typedid diff --git a/src/StronglyTypedIds/StronglyTypedIds.csproj b/src/StronglyTypedIds/StronglyTypedIds.csproj index 5117fdd09..a61535bd3 100644 --- a/src/StronglyTypedIds/StronglyTypedIds.csproj +++ b/src/StronglyTypedIds/StronglyTypedIds.csproj @@ -24,7 +24,10 @@ - + + + + @@ -34,9 +37,4 @@ - - - - - \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj b/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj index 00a218283..ecb695358 100644 --- a/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj +++ b/test/StronglyTypedIds.IntegrationTests/StronglyTypedIds.IntegrationTests.csproj @@ -14,7 +14,7 @@ - + diff --git a/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj b/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj index f6eeea42e..7e9d04e7c 100644 --- a/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj +++ b/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj @@ -18,6 +18,7 @@ + diff --git a/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj b/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj index 22322fa34..e4749e998 100644 --- a/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj +++ b/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj @@ -17,6 +17,7 @@ + From 9dd9f086ecc27952992ae54b495b13215716c9bf Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Wed, 8 Nov 2023 08:32:58 +0000 Subject: [PATCH 22/47] Add some optional "partial" templates --- .../guid-dapper.typedid | 9 ++++++++ .../guid-efcore.typedid | 13 +++++++++++ .../guid-newtonsoftjson.typedid | 22 +++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 src/StronglyTypedIds.Templates/guid-dapper.typedid create mode 100644 src/StronglyTypedIds.Templates/guid-efcore.typedid create mode 100644 src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid diff --git a/src/StronglyTypedIds.Templates/guid-dapper.typedid b/src/StronglyTypedIds.Templates/guid-dapper.typedid new file mode 100644 index 000000000..d56f7d85a --- /dev/null +++ b/src/StronglyTypedIds.Templates/guid-dapper.typedid @@ -0,0 +1,9 @@ + partial struct PLACEHOLDERID + { + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/guid-efcore.typedid b/src/StronglyTypedIds.Templates/guid-efcore.typedid new file mode 100644 index 000000000..4c8af273f --- /dev/null +++ b/src/StronglyTypedIds.Templates/guid-efcore.typedid @@ -0,0 +1,13 @@ + partial struct PLACEHOLDERID + { + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid new file mode 100644 index 000000000..5fe6395c2 --- /dev/null +++ b/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid @@ -0,0 +1,22 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID + { + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var guid = serializer.Deserialize(reader); + return guid.HasValue ? new PLACEHOLDERID(guid.Value) : null; + } + } + } \ No newline at end of file From b83338376819fc1c62eca0083f2a0ac9895e00b7 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Wed, 8 Nov 2023 08:42:55 +0000 Subject: [PATCH 23/47] Try to fix tests --- .../Enums.cs | 19 +------------------ .../StronglyTypedIds.Tests.csproj | 2 +- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index 6c4c1f1c9..3e8c7dbd1 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -38,24 +38,7 @@ partial struct NewIdId1 { } partial struct NewIdId2 { } [StronglyTypedId(Template.String)] -partial struct StringId -{ - public bool TryFormat2( - global::System.Span destination, - out int charsWritten, - global::System.ReadOnlySpan format = default) - { - if (destination.Length > Value.Length) - { - MemoryExtensions.AsSpan(Value).CopyTo(destination); - charsWritten = Value.Length; - return true; - } - - charsWritten = default; - return false; - } -} +partial struct StringId { } [StronglyTypedId("string-full")] partial struct ConvertersStringId { } diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj index caf11f1b1..4ef5fe171 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj +++ b/test/StronglyTypedIds.Tests/StronglyTypedIds.Tests.csproj @@ -19,7 +19,7 @@ - + From 41c3d021621c171ee285b55639909cb38922e57e Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Wed, 8 Nov 2023 09:00:10 +0000 Subject: [PATCH 24/47] Remove the built-in templates from the generator tests They just add noise --- ...ateDefaultIdInGlobalNamespace.verified.txt | 153 ------------------ ....CanGenerateForCustomTemplate.verified.txt | 153 ------------------ ...yNestedIdInFileScopeNamespace.verified.txt | 153 ------------------ ...nerateIdInFileScopedNamespace.verified.txt | 153 ------------------ ...ests.CanGenerateIdInNamespace.verified.txt | 153 ------------------ ...nerateMultipleIdsWithSameName.verified.txt | 153 ------------------ ...eNestedIdInFileScopeNamespace.verified.txt | 153 ------------------ ...nerateNonDefaultIdInNamespace.verified.txt | 153 ------------------ ...yNestedIdInFileScopeNamespace.verified.txt | 153 ------------------ ...mTemplateUsingGlobalAttribute.verified.txt | 153 ------------------ ...hTemplateUsingGlobalAttribute.verified.txt | 153 ------------------ .../StronglyTypedIdGeneratorTests.cs | 22 +-- test/StronglyTypedIds.Tests/TestHelpers.cs | 10 +- 13 files changed, 19 insertions(+), 1696 deletions(-) diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index aab895549..877dfdd5b 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt index cf6565528..a8d5b3f3a 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable namespace SomeNamespace { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt index 875dc81f1..1755bd1b1 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable namespace SomeNamespace { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index 9ca113834..94d4c33f8 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable namespace SomeNamespace { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index 9ca113834..94d4c33f8 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable namespace SomeNamespace { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 2e0fa5643..73834c603 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable namespace MyContracts.V1 { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index 18be5df5c..43447a354 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable namespace SomeNamespace { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index 54d2abebc..952445ebe 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable namespace SomeNamespace { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index a7064e440..ea59d6ba8 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable namespace SomeNamespace { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt index 7133d9a9a..02eb53fdd 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index 325b12247..75cce0f27 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -9,159 +9,6 @@ #pragma warning disable 1591 // publicly visible type or member must be documented -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - #nullable enable [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs index ebaf90a20..f5d7f67de 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs +++ b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs @@ -24,7 +24,7 @@ public Task CanGenerateDefaultIdInGlobalNamespace() [StronglyTypedId] public partial struct MyId {}"; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -45,7 +45,7 @@ namespace SomeNamespace public partial struct MyId {} } """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -65,7 +65,7 @@ namespace SomeNamespace public partial struct MyId {} } """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -85,7 +85,7 @@ namespace SomeNamespace public partial struct MyId {} } """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -102,7 +102,7 @@ public Task CanGenerateIdInFileScopedNamespace() namespace SomeNamespace; [StronglyTypedId] public partial struct MyId {}"; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -122,7 +122,7 @@ public class ParentClass [StronglyTypedId] public partial struct MyId {} }"; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -148,7 +148,7 @@ public readonly partial struct MyId {} } } }"; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -175,7 +175,7 @@ public partial struct MyId {} } } }"; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -194,7 +194,7 @@ public Task CanOverrideDefaultsWithTemplateUsingGlobalAttribute() public partial struct MyId {} """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -213,7 +213,7 @@ public Task CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute() public partial struct MyId {} """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); @@ -240,7 +240,7 @@ public partial struct MyId {} }"; // This only includes the last ID but that's good enough for this - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Empty(diagnostics); diff --git a/test/StronglyTypedIds.Tests/TestHelpers.cs b/test/StronglyTypedIds.Tests/TestHelpers.cs index 2300a54e6..791ec5fce 100644 --- a/test/StronglyTypedIds.Tests/TestHelpers.cs +++ b/test/StronglyTypedIds.Tests/TestHelpers.cs @@ -14,7 +14,7 @@ namespace StronglyTypedIds.Tests { internal static class TestHelpers { - public static (ImmutableArray Diagnostics, string Output) GetGeneratedOutput(string source) + public static (ImmutableArray Diagnostics, string Output) GetGeneratedOutput(string source, bool includeAttributes = true) where T : IIncrementalGenerator, new() { var attr = new StronglyTypedIdAttribute(); @@ -35,7 +35,13 @@ public static (ImmutableArray Diagnostics, string Output) GetGenerat .Create(new T()) .AddAdditionalTexts(LoadEmbeddedResourcesAsAdditionalText()) .RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var diagnostics); - var output = string.Join("\n", outputCompilation.SyntaxTrees.Skip(originalTreeCount).Select(t => t.ToString())); + + // If we don't want the attributes, we try to get all the potential resource streams and exclude them + var countsToExclude = includeAttributes + ? originalTreeCount + : originalTreeCount + typeof(T).Assembly.GetManifestResourceNames().Count(x => x.StartsWith("StronglyTypedIds.Templates.Sources.")); + + var output = string.Join("\n", outputCompilation.SyntaxTrees.Skip(countsToExclude).Select(t => t.ToString())); return (diagnostics, output); } From f32e1703b99b826b700f3dc06b9475f53537842f Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 10 Nov 2023 19:24:02 +0000 Subject: [PATCH 25/47] Support adding multiple templates in one attribute --- .../StronglyTypedIdAttribute.cs | 36 +-- .../StronglyTypedIdDefaultsAttribute.cs | 23 +- .../InvalidTemplateNameDiagnostic.cs | 4 +- src/StronglyTypedIds/Parser.cs | 219 ++++++++++++------ .../SourceGenerationHelper.cs | 14 +- .../StronglyTypedIdGenerator.cs | 213 ++++++++++++----- src/StronglyTypedIds/StructToGenerate.cs | 34 +-- .../DiagnosticsTests.cs | 40 +--- test/StronglyTypedIds.Tests/EqualityTests.cs | 23 +- ...urce=StronglyTypedIdAttribute.verified.txt | 36 +-- ...onglyTypedIdDefaultsAttribute.verified.txt | 23 +- .../Snapshots/NoGeneratedIds.verified.txt | 153 ------------ .../StronglyTypedIdGeneratorTests.cs | 41 ++-- 13 files changed, 423 insertions(+), 436 deletions(-) delete mode 100644 test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt diff --git a/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs b/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs index a8b1fe8ea..6f6ea829d 100644 --- a/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs +++ b/src/StronglyTypedIds.Attributes/StronglyTypedIdAttribute.cs @@ -16,7 +16,7 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] public sealed class StronglyTypedIdAttribute : global::System.Attribute { @@ -24,38 +24,26 @@ public sealed class StronglyTypedIdAttribute : global::System.Attribute /// Make the struct a strongly typed ID. /// /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) + /// The names of additional custom templates to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template, params string[] templateNames) { - Template = template; } /// /// Make the struct a strongly typed ID. /// - /// The name of the template to use to generate the ID. + /// The names of the template to use to generate the ID. /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . + /// where NAME is the name of the template passed in . + /// If no templates are provided, the default value is used, as specified by + /// , or alternatively the + /// template. /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() + public StronglyTypedIdAttribute(params string[] templateNames) { } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } } } \ No newline at end of file diff --git a/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs b/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs index 97ebf0c64..c4518e1ef 100644 --- a/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs +++ b/src/StronglyTypedIds.Attributes/StronglyTypedIdDefaultsAttribute.cs @@ -25,9 +25,12 @@ public sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) + /// The names of additional custom templates to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template, params string[] templateNames) { - Template = template; } /// @@ -39,17 +42,17 @@ public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template templa /// public StronglyTypedIdDefaultsAttribute(string templateName) { - TemplateName = templateName; } /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. + /// Set the default template to use for strongly typed IDs /// - public string? TemplateName { get; } + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName, params string[] templateNames) + { + } } } \ No newline at end of file diff --git a/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs index 2997eeea1..be8b4700b 100644 --- a/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs @@ -8,8 +8,8 @@ internal static class InvalidTemplateNameDiagnostic internal const string Message = "The template name must not be null or whitespace."; internal const string Title = "Invalid template name"; - public static DiagnosticInfo CreateInfo(SyntaxNode currentNode) + public static DiagnosticInfo CreateInfo(LocationInfo location) => new(new DiagnosticDescriptor( Id, Title, Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true), - currentNode.GetLocation()); + location.ToLocation()); } \ No newline at end of file diff --git a/src/StronglyTypedIds/Parser.cs b/src/StronglyTypedIds/Parser.cs index 4c75e9344..2f4162f89 100644 --- a/src/StronglyTypedIds/Parser.cs +++ b/src/StronglyTypedIds/Parser.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Threading; using Microsoft.CodeAnalysis; @@ -25,8 +26,8 @@ internal static class Parser var hasMisconfiguredInput = false; List? diagnostics = null; Template? template = null; - string? templateName = null; - LocationInfo? templateLocation = null; + string[]? templateNames = null; + LocationInfo? attributeLocation = null; foreach (AttributeData attribute in structSymbol.GetAttributes()) { @@ -38,7 +39,13 @@ internal static class Parser continue; } - hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName, out templateLocation, ref diagnostics); + (var result, (template, templateNames)) = GetConstructorValues(attribute); + hasMisconfiguredInput |= result; + + if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } s) + { + attributeLocation = LocationInfo.CreateFrom(s); + } } var hasPartialModifier = false; @@ -70,9 +77,13 @@ internal static class Parser ParentClass? parentClass = GetParentClasses(structSyntax); var name = structSymbol.Name; - var toGenerate = template.HasValue - ? new StructToGenerate(name: name, nameSpace: nameSpace, template: template.Value, parent: parentClass) - : new StructToGenerate(name: name, nameSpace: nameSpace, templateName: templateName, templateLocation: templateLocation!, parent: parentClass); + var toGenerate =new StructToGenerate( + name: name, + nameSpace: nameSpace, + template: template, + templateNames: templateNames, + templateLocation: attributeLocation!, + parent: parentClass); return new Result<(StructToGenerate, bool)>((toGenerate, true), errors); } @@ -87,9 +98,9 @@ internal static class Parser } // We only return the first config that we find - string? templateName = null; + string[]? templateNames = null; Template? template = null; - LocationInfo? templateLocation = null; + LocationInfo? attributeLocation = null; List? diagnostics = null; bool hasMisconfiguredInput = false; bool hasMultiple = false; @@ -106,17 +117,24 @@ internal static class Parser continue; } - if (!string.IsNullOrWhiteSpace(templateName) || template.HasValue) + var syntax = attribute.ApplicationSyntaxReference?.GetSyntax(); + if (templateNames is not null || template.HasValue || hasMisconfiguredInput) { hasMultiple = true; - if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } s) + if (syntax is not null) { diagnostics ??= new(); - diagnostics.Add(MultipleAssemblyAttributeDiagnostic.CreateInfo(s)); + diagnostics.Add(MultipleAssemblyAttributeDiagnostic.CreateInfo(syntax)); } } - hasMisconfiguredInput |= GetConstructorValues(attribute, out template, out templateName, out templateLocation, ref diagnostics); + (var result, (template, templateNames)) = GetConstructorValues(attribute); + hasMisconfiguredInput |= result; + + if (syntax is not null) + { + attributeLocation = LocationInfo.CreateFrom(syntax); + } } var errors = diagnostics is null @@ -128,104 +146,161 @@ internal static class Parser return new Result<(Defaults, bool)>((default, false), errors); } - var defaults = template.HasValue - ? new Defaults(template.Value, hasMultiple) - : new Defaults(templateName!, templateLocation!, hasMultiple); + var defaults = new Defaults(template, templateNames, attributeLocation!, hasMultiple); return new Result<(Defaults, bool)>((defaults, true), errors); } - private static bool GetConstructorValues(AttributeData attribute, out Template? template, out string? templateName, out LocationInfo? templateLocation, ref List? diagnostics) + private static (bool HasMisconfiguredInput, (Template? Template, string[]? TemplateNames)) GetConstructorValues(AttributeData attribute) { - var hasMisconfiguredInput = false; - template = null; - templateName = null; - templateLocation = null; + (Template? Template, string? Name, string[]? Names)? results1 = null; + (Template? Template, string? Name, string[]? Names)? results2 = null; if (attribute.ConstructorArguments is { IsEmpty: false } args) { - // make sure we don't have any errors - foreach (TypedConstant arg in args) + // we should have at most 2 args (params count as one arg) + if (args.Length > 2) { - if (arg.Kind == TypedConstantKind.Error) - { - // have an error, so don't try and do any generation - hasMisconfiguredInput = true; - break; - } + // have an error, so don't try and do any generation + return (true, default); } - if (args[0].Value is int enumValue) + // Should always have at least one arg, but it might be an empty array + var (success, results) = TryGetTypedConstant(args[0]); + + if (success) { - template = (Template) enumValue; + results1 = results; } else { - templateName = args[0].Value as string; - var syntaxNode = attribute.ApplicationSyntaxReference?.GetSyntax(); - if (string.IsNullOrWhiteSpace(templateName)) - { - if (syntaxNode is { } s) - { - diagnostics ??= new(); - diagnostics.Add(InvalidTemplateNameDiagnostic.CreateInfo(s)); - } + // have an error, so don't try and do any generation + return (true, default); + } + + if (args.Length == 2) + { + (success, results) = TryGetTypedConstant(args[1]); - hasMisconfiguredInput = true; + if (success) + { + results2 = results; } else { - if (syntaxNode is { } s) - { - templateLocation = LocationInfo.CreateFrom(s); - } + // have an error, so don't try and do any generation + return (true, default); } } } - + if (attribute.NamedArguments is { IsEmpty: false } namedArgs) { foreach (KeyValuePair arg in namedArgs) { - TypedConstant typedConstant = arg.Value; - if (typedConstant.Kind == TypedConstantKind.Error) - { - hasMisconfiguredInput = true; - break; - } + // Should always have at least one arg, but it might be an empty array + var (success, results) = TryGetTypedConstant(arg.Value); - if (typedConstant.Value is int enumValue) - { - template = (Template) enumValue; - } - else + if (success) { - templateName = typedConstant.Value as string; - var syntaxNode = attribute.ApplicationSyntaxReference?.GetSyntax(); - if (string.IsNullOrWhiteSpace(templateName)) + if (results1 is null) { - if (syntaxNode is { } s) - { - diagnostics ??= new(); - diagnostics.Add(InvalidTemplateNameDiagnostic.CreateInfo(s)); - } - - hasMisconfiguredInput = true; + results1 = results; + } + else if(results2 is null) + { + results2 = results; } else { - if (syntaxNode is { } s) - { - templateLocation = LocationInfo.CreateFrom(s); - } + // must be an error + return (true, default); } } + else + { + // have an error, so don't try and do any generation + return (true, default); + } + } + } - break; + + // consolidate + var template = results1?.Template ?? results2?.Template; + var name = results1?.Name ?? results2?.Name; + var names = results1?.Names ?? results2?.Names; + + if (name is not null) + { + if (names is {Length: > 0} ns) + { + names = new string[ns.Length + 1]; + ns.CopyTo(names, 0); + names[^1] = name; + } + else + { + names = new[] {name}; } } - return hasMisconfiguredInput; + return (false, (template, names)); + + static (bool IsValid, (Template? Template, string? Name, string[]? Names)) TryGetTypedConstant(in TypedConstant arg) + { + if (arg.Kind is TypedConstantKind.Error) + { + return (false, default); + } + + if (arg.Kind is TypedConstantKind.Primitive + && arg.Value is string stringValue) + { + var name = string.IsNullOrWhiteSpace(stringValue) + ? string.Empty + : stringValue; + + return (true, (null, name, null)); + } + + if (arg.Kind is TypedConstantKind.Enum + && arg.Value is int intValue) + { + return (true, ((Template) intValue, null, null)); + } + + if (arg.Kind is TypedConstantKind.Array) + { + var values = arg.Values; + + // if null is passed, it's treated the same as an empty array + if (values.IsDefaultOrEmpty) + { + return (true, (null, null, Array.Empty())); + } + + var names = new string[values.Length]; + for (var i = 0; i < values.Length; i++) + { + if (values[i].Kind == TypedConstantKind.Error) + { + // Abandon generation + return (false, default); + } + + var value = values[i].Value as string; + names[i] = string.IsNullOrWhiteSpace(value) + ? string.Empty + : value!; + } + + return (true, (null, null, names)); + } + + // Some other type, weird, shouldn't be able to get this + return (false, default); + } } private static string GetNameSpace(StructDeclarationSyntax structSymbol) diff --git a/src/StronglyTypedIds/SourceGenerationHelper.cs b/src/StronglyTypedIds/SourceGenerationHelper.cs index c435d7fa5..ab58f39ca 100644 --- a/src/StronglyTypedIds/SourceGenerationHelper.cs +++ b/src/StronglyTypedIds/SourceGenerationHelper.cs @@ -85,9 +85,10 @@ public static string CreateId( return sb.ToString(); } - internal static string CreateSourceName(string nameSpace, ParentClass? parent, string name) + internal static string CreateSourceName(StringBuilder sb, string nameSpace, ParentClass? parent, string name, string template) { - var sb = new StringBuilder(nameSpace).Append('.'); + sb.Clear(); + sb.Append(nameSpace).Append('.'); while (parent is { } p) { var s = p.Name @@ -98,7 +99,14 @@ internal static string CreateSourceName(string nameSpace, ParentClass? parent, s sb.Append(s).Append('.'); parent = p.Child; } - return sb.Append(name).Append(".g.cs").ToString(); + + sb.Append(name); + if (!string.IsNullOrEmpty(template)) + { + sb.Append(template).Append('.'); + } + + return sb.Append(".g.cs").ToString(); } } } diff --git a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs index 1603fa51b..b77f18686 100644 --- a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs +++ b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs @@ -64,7 +64,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Where(static x => x.Value.valid) .Select((result, _) => result.Value.info); - IncrementalValueProvider<(string? Content, bool isValid, bool IsBuiltIn, DiagnosticInfo? Diagnostic)> defaultTemplateContent = defaultsAndDiagnostics + IncrementalValueProvider<(EquatableArray<(string Name, string Content)> Content, bool isValid, DiagnosticInfo? Diagnostic)> defaultTemplateContent = defaultsAndDiagnostics .Where(static x => x.Value.valid) .Select((result, _) => result.Value.defaults) .Collect() @@ -74,48 +74,63 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (all.Left.IsDefaultOrEmpty) { // no default attributes, valid, but no content - return (null, true, true, null); + return (EquatableArray<(string Name, string Content)>.Empty, true, null); } // technically we can never have more than one `Defaults` here // but check for it just in case if (all.Left is {IsDefaultOrEmpty: false, Length: > 1}) { - return (null, false, true, null); + return (EquatableArray<(string Name, string Content)>.Empty, false, null); } var defaults = all.Left[0]; if (defaults.HasMultiple) { // not valid - return (null, false, true, null); + return (EquatableArray<(string Name, string Content)>.Empty, false, null); } + (string, string)? builtInTemplate = null; if (defaults.Template is { } templateId) { // Explicit template - return ((string?) EmbeddedSources.GetTemplate(templateId), true, true, (DiagnosticInfo?) null); + builtInTemplate = (string.Empty, EmbeddedSources.GetTemplate(templateId)); } - // We have already checked for a null template name and flagged it as an error - var defaultsTemplateName = defaults.TemplateName; - if(!string.IsNullOrEmpty(defaultsTemplateName)) + var templateNames = defaults.TemplateNames.GetArray(); + if (templateNames is null or {Length: 0}) { - foreach (var templateDetails in all.Right) + if (builtInTemplate.HasValue) { - if (string.Equals(templateDetails.Name, defaultsTemplateName, StringComparison.Ordinal)) - { - // This _could_ be empty, but we use it anyway (and add a comment in the template) - return (templateDetails.Content ?? GetEmptyTemplateContent(defaultsTemplateName!), true, false, null); - } + // valid, only built-in + var template = new EquatableArray<(string Name, string Content)>(new[] {builtInTemplate.Value}); + return (template, true, (DiagnosticInfo?) null); } - - // Template name specified, but we don't have a template for it - return (null, false, true, UnknownTemplateDiagnostic.CreateInfo(defaults.TemplateLocation!, defaultsTemplateName!)); + + // not valid, need something + return (EquatableArray<(string Name, string Content)>.Empty, false, null); + } + + // We have already checked for null/empty template name and flagged it as an error + if (!GetContent( + templateNames, + defaults.TemplateLocation!, + builtInTemplate.HasValue, + in all.Right, + out var contents, + out var diagnostic)) + { + return (EquatableArray<(string Name, string Content)>.Empty, false, diagnostic); } - - // only get here if the template name was null/empty, which is already reported - return (null, false, true, null); + + if (builtInTemplate.HasValue) + { + contents[^1] = builtInTemplate.Value; + } + + // Ok, we have all the templates + return (new EquatableArray<(string Name, string Content)>(contents), true, null); }); var structsWithDefaultsAndTemplates = structs @@ -129,96 +144,168 @@ public void Initialize(IncrementalGeneratorInitializationContext context) private static void Execute( StructToGenerate idToGenerate, ImmutableArray<(string Path, string Name, string? Content)> templates, - (string? Content, bool IsValid, bool IsBuiltInTemplate, DiagnosticInfo? Diagnostics) defaults, + (EquatableArray<(string Name, string Content)>, bool IsValid, DiagnosticInfo? Diagnostic) defaults, SourceProductionContext context) { var sb = new StringBuilder(); - if (defaults.Diagnostics is { } diagnostic) + if (defaults.Diagnostic is { } diagnostic) { // report error with the default template context.ReportDiagnostic(diagnostic); } - if (!TryGetTemplateContent(idToGenerate, templates, defaults, in context, out var templateContent, out var addDefaultAttributes)) + if (!TryGetTemplateContent(idToGenerate, templates, defaults, in context, out var templateContents)) { return; } - var result = SourceGenerationHelper.CreateId( - idToGenerate.NameSpace, - idToGenerate.Name, - idToGenerate.Parent, - templateContent, - addDefaultAttributes, - sb); - - var fileName = SourceGenerationHelper.CreateSourceName( - idToGenerate.NameSpace, - idToGenerate.Parent, - idToGenerate.Name); - context.AddSource(fileName, SourceText.From(result, Encoding.UTF8)); + foreach (var (name, content) in templateContents) + { + var result = SourceGenerationHelper.CreateId( + idToGenerate.NameSpace, + idToGenerate.Name, + idToGenerate.Parent, + content, + addDefaultAttributes: string.IsNullOrEmpty(name), + sb); + + var fileName = SourceGenerationHelper.CreateSourceName( + sb, + idToGenerate.NameSpace, + idToGenerate.Parent, + idToGenerate.Name, + name); + + context.AddSource(fileName, SourceText.From(result, Encoding.UTF8)); + } } private static bool TryGetTemplateContent( in StructToGenerate idToGenerate, in ImmutableArray<(string Path, string Name, string? Content)> templates, - (string? Content, bool IsValid, bool IsBuiltInTemplate, DiagnosticInfo? Diagnostics) defaults, + (EquatableArray<(string Name, string Content)> Contents, bool IsValid, DiagnosticInfo? Diagnostics) defaults, in SourceProductionContext context, - [NotNullWhen(true)] out string? templateContent, - out bool addDefaultAttributes) + [NotNullWhen(true)] out (string Name, string Content)[]? templateContents) { - // built-in template specified + (string, string)? builtIn = null; if (idToGenerate.Template is { } templateId) { - templateContent = EmbeddedSources.GetTemplate(templateId); - addDefaultAttributes = true; - return true; + // built-in template specified + var content = EmbeddedSources.GetTemplate(templateId); + builtIn = (string.Empty, content); } - // custom template specified - if (!string.IsNullOrEmpty(idToGenerate.TemplateName)) + if (idToGenerate.TemplateNames.GetArray() is {Length: > 0} templateNames) { - foreach (var templateDetails in templates) + // custom template specified + if (GetContent( + templateNames, + idToGenerate.TemplateLocation, + builtIn.HasValue, + in templates, + out templateContents, + out var diagnostic)) { - if (string.Equals(templateDetails.Name, idToGenerate.TemplateName, StringComparison.Ordinal)) + if (builtIn.HasValue) { - templateContent = templateDetails.Content ?? GetEmptyTemplateContent(idToGenerate.TemplateName!); - addDefaultAttributes = false; - return true; + templateContents[^1] = builtIn.Value; } + + return true; } - // the template wasn't found, so it must be invalid. Don't generate anything - var info = UnknownTemplateDiagnostic.CreateInfo(idToGenerate.TemplateLocation!, idToGenerate.TemplateName!); - context.ReportDiagnostic(info); - templateContent = null; - addDefaultAttributes = false; + // One of the templates wasn't found, so it must be invalid. Don't generate anything + if (diagnostic is { }) + { + context.ReportDiagnostic(diagnostic); + } + + templateContents = null; return false; } - // nothing specified, use the default (if we have one) + if (builtIn.HasValue) + { + templateContents = new[] {builtIn.Value}; + return true; + } + + // nothing specified, use the defaults (if we have them) if (defaults.IsValid) { - if (defaults.Content is { } content) + if (defaults.Contents.GetArray() is {Length: > 0} allContent) { - templateContent = content; - addDefaultAttributes = defaults.IsBuiltInTemplate; + templateContents = allContent; } else { - templateContent = EmbeddedSources.GetTemplate(Template.Guid); - addDefaultAttributes = true; + templateContents = new[] {(string.Empty, EmbeddedSources.GetTemplate(Template.Guid))}; } return true; } - templateContent = null; - addDefaultAttributes = true; + // not valid + templateContents = null; return false; } private static string GetEmptyTemplateContent(string templateName) => $"// The {templateName}.typeid template was empty, you'll need to add some content"; + + private static bool GetContent( + string[] templateNames, + LocationInfo? location, + bool haveStandardTemplate, + in ImmutableArray<(string Path, string Name, string? Content)> templates, + [NotNullWhen(true)] out (string Name, string Content)[]? output, + out DiagnosticInfo? diagnostic) + { + // Length + 1 to optionally add the extra template + var totalTemplates = haveStandardTemplate ? templateNames.Length + 1 : templateNames.Length; + (string, string)[]? contents = null; + for (int i = 0; i < templateNames.Length; i++) + { + var templateName = templateNames[i]; + if (string.IsNullOrEmpty(templateName)) + { + output = null; + diagnostic = location is not null + ? InvalidTemplateNameDiagnostic.CreateInfo(location) + : null; + return false; + } + + var foundTemplate = false; + + foreach (var templateDetails in templates) + { + if (string.Equals(templateDetails.Name, templateName, StringComparison.Ordinal)) + { + // This _could_ be empty, but we use it anyway (and add a comment in the template) + var content = templateDetails.Content ?? GetEmptyTemplateContent(templateName); + contents ??= new (string, string)[totalTemplates]; + contents[i] = (templateName, content); + foundTemplate = true; + break; + } + } + + if (!foundTemplate) + { + // Template name specified, but we don't have a template for it + // bail out early + output = null; + diagnostic = location is not null + ? UnknownTemplateDiagnostic.CreateInfo(location, templateName) + : null; + return false; + } + } + + output = contents!; // only case this wouldn't be true is if templateNames is empty + diagnostic = null; + return true; + } } } \ No newline at end of file diff --git a/src/StronglyTypedIds/StructToGenerate.cs b/src/StronglyTypedIds/StructToGenerate.cs index 3f3945ba9..2f2a666c7 100644 --- a/src/StronglyTypedIds/StructToGenerate.cs +++ b/src/StronglyTypedIds/StructToGenerate.cs @@ -6,29 +6,19 @@ namespace StronglyTypedIds; internal readonly record struct StructToGenerate { - public StructToGenerate(string name, string nameSpace, string? templateName, ParentClass? parent, LocationInfo templateLocation) + public StructToGenerate(string name, string nameSpace, Template? template, string[]? templateNames, ParentClass? parent, LocationInfo templateLocation) { Name = name; NameSpace = nameSpace; - TemplateName = templateName; - Template = null; - Parent = parent; - TemplateLocation = templateLocation; - } - - public StructToGenerate(string name, string nameSpace, Template template, ParentClass? parent) - { - Name = name; - NameSpace = nameSpace; - TemplateName = null; + TemplateNames = templateNames is null ? EquatableArray.Empty : new EquatableArray(templateNames); Template = template; Parent = parent; - TemplateLocation = null; + TemplateLocation = templateLocation; } public string Name { get; } public string NameSpace { get; } - public string? TemplateName { get; } + public EquatableArray TemplateNames { get; } public Template? Template { get; } public ParentClass? Parent { get; } public LocationInfo? TemplateLocation { get; } @@ -44,23 +34,15 @@ internal sealed record Result(TValue Value, EquatableArray.Empty : new EquatableArray(templateNames); HasMultiple = hasMultiple; - Template = null; - TemplateLocation = location; - } - - public Defaults(Template template, bool hasMultiple) - { - TemplateName = null; Template = template; - HasMultiple = hasMultiple; - TemplateLocation = null; + TemplateLocation = location; } - public string? TemplateName { get; } + public EquatableArray TemplateNames { get; } public Template? Template { get; } public LocationInfo? TemplateLocation { get; } public bool HasMultiple { get; } diff --git a/test/StronglyTypedIds.Tests/DiagnosticsTests.cs b/test/StronglyTypedIds.Tests/DiagnosticsTests.cs index 4c1de7a82..b809fb657 100644 --- a/test/StronglyTypedIds.Tests/DiagnosticsTests.cs +++ b/test/StronglyTypedIds.Tests/DiagnosticsTests.cs @@ -12,10 +12,9 @@ public class DiagnosticsTests public const string NoIdGenerationSnapshotName = "NoGeneratedIds"; [Theory] - [InlineData("null")] [InlineData("\"\"")] [InlineData("\" \"")] - public Task EmptyTemplate_GivesInvalidTemplateNameDiagnostic_AndDoesntGenerate(string template) + public void EmptyTemplate_GivesInvalidTemplateNameDiagnostic_AndDoesntGenerate(string template) { var input = $$""" using StronglyTypedIds; @@ -23,18 +22,14 @@ public Task EmptyTemplate_GivesInvalidTemplateNameDiagnostic_AndDoesntGenerate(s [StronglyTypedId({{template}})] public partial struct MyId {} """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Contains(diagnostics, diagnostic => diagnostic.Id == InvalidTemplateNameDiagnostic.Id); - - return Verifier.Verify(output) - .DisableRequireUniquePrefix() - .UseDirectory("Snapshots") - .UseFileName(NoIdGenerationSnapshotName); + Assert.Empty(output); } [Fact] - public Task MultipleAssemblyAttributes_GivesMultipleAttributeDiagnostic_AndDoesntGenerate() + public void MultipleAssemblyAttributes_GivesMultipleAttributeDiagnostic_AndDoesntGenerate() { const string input = """ using StronglyTypedIds; @@ -44,18 +39,14 @@ public Task MultipleAssemblyAttributes_GivesMultipleAttributeDiagnostic_AndDoesn [StronglyTypedId] public partial struct MyId {} """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Contains(diagnostics, diagnostic => diagnostic.Id == MultipleAssemblyAttributeDiagnostic.Id); - - return Verifier.Verify(output) - .DisableRequireUniquePrefix() - .UseDirectory("Snapshots") - .UseFileName(NoIdGenerationSnapshotName); + Assert.Empty(output); } [Fact] - public Task InvalidTemplate_GivesDiagnostic_AndDoesntGenerate() + public void InvalidTemplate_GivesDiagnostic_AndDoesntGenerate() { const string input = """ using StronglyTypedIds; @@ -63,18 +54,14 @@ public Task InvalidTemplate_GivesDiagnostic_AndDoesntGenerate() [StronglyTypedId("some-template")] public partial struct MyId {} """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Contains(diagnostics, diagnostic => diagnostic.Id == UnknownTemplateDiagnostic.Id); - - return Verifier.Verify(output) - .DisableRequireUniquePrefix() - .UseDirectory("Snapshots") - .UseFileName(NoIdGenerationSnapshotName); + Assert.Empty(output); } [Fact] - public Task InvalidTemplateInDefaultsAttribute_GivesDiagnostic_AndDoesntGenerate() + public void InvalidTemplateInDefaultsAttribute_GivesDiagnostic_AndDoesntGenerate() { const string input = """ using StronglyTypedIds; @@ -83,13 +70,10 @@ public Task InvalidTemplateInDefaultsAttribute_GivesDiagnostic_AndDoesntGenerate [StronglyTypedId] public partial struct MyId {} """; - var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input); + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); Assert.Contains(diagnostics, diagnostic => diagnostic.Id == UnknownTemplateDiagnostic.Id); - return Verifier.Verify(output) - .DisableRequireUniquePrefix() - .UseDirectory("Snapshots") - .UseFileName(NoIdGenerationSnapshotName); + Assert.Empty(output); } } \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/EqualityTests.cs b/test/StronglyTypedIds.Tests/EqualityTests.cs index 5d5c0e9e2..840276066 100644 --- a/test/StronglyTypedIds.Tests/EqualityTests.cs +++ b/test/StronglyTypedIds.Tests/EqualityTests.cs @@ -7,6 +7,8 @@ namespace StronglyTypedIds.Tests; public class EqualityTests { + private static LocationInfo _templateLocation = new("Some path", new TextSpan(0, 100), new LinePositionSpan(new LinePosition(23, 2), new LinePosition(23, 15))); + [Fact] public void ParentClassHasExpectedEqualityBehaviour() { @@ -48,7 +50,9 @@ StructToGenerate GetStruct() => name: "MyStruct", nameSpace: "MyNamespace", template: Template.Guid, - parent: null); + null, + parent: null, + _templateLocation); } [Fact] @@ -65,8 +69,9 @@ StructToGenerate GetStruct() => new( name: "MyStruct", nameSpace: "MyNamespace", - templateName: "Guid", - templateLocation: new LocationInfo("Some path", new TextSpan(0, 100), new LinePositionSpan(new LinePosition(23, 2), new LinePosition(23, 15))), + template: Template.Int, + templateNames: new[] {"Guid"}, + templateLocation: _templateLocation, parent: null); } @@ -86,7 +91,9 @@ StructToGenerate GetStruct() name: "MyStruct", nameSpace: "MyNamespace", template: Template.Guid, - parent: new ParentClass(null, "class", "b", "", null, false)); + templateNames: null, + parent: new ParentClass(null, "class", "b", "", null, false), + _templateLocation); } } @@ -106,7 +113,9 @@ public void ResultWithoutDiagnosticHasExpectedEqualityBehaviour() name: "MyStruct", nameSpace: "MyNamespace", template: Template.Guid, - parent: new ParentClass(null, "class", "b", "", null, false)); + templateNames: null, + parent: new ParentClass(null, "class", "b", "", null, false), + _templateLocation); return new Result<(StructToGenerate, bool)>((instance, true), new EquatableArray()); } @@ -128,7 +137,9 @@ public void ResultWithDiagnosticHasExpectedEqualityBehaviour() name: "MyStruct", nameSpace: "MyNamespace", template: Template.Guid, - parent: new ParentClass(null, "class", "b", "", null, false)); + templateNames: null, + parent: new ParentClass(null, "class", "b", "", null, false), + _templateLocation); var diagnostics = new DiagnosticInfo(new DiagnosticDescriptor( NotPartialDiagnostic.Id, NotPartialDiagnostic.Title, NotPartialDiagnostic.Message, category: Constants.Usage, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true), diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt index ffe2528a8..59dc3731d 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdAttribute.verified.txt @@ -18,7 +18,7 @@ namespace StronglyTypedIds /// /// Place on partial structs to make the type a strongly-typed ID /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] + [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] internal sealed class StronglyTypedIdAttribute : global::System.Attribute { @@ -26,39 +26,27 @@ namespace StronglyTypedIds /// Make the struct a strongly typed ID. /// /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) + /// The names of additional custom templates to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template, params string[] templateNames) { - Template = template; } /// /// Make the struct a strongly typed ID. /// - /// The name of the template to use to generate the ID. + /// The names of the template to use to generate the ID. /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . + /// where NAME is the name of the template passed in . + /// If no templates are provided, the default value is used, as specified by + /// , or alternatively the + /// template. /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() + public StronglyTypedIdAttribute(params string[] templateNames) { } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } } } #endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt index cd82ba82f..3dd6d36b4 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/EmbeddedResourceTests.EmittedResourceIsSameAsCompiledResource_resource=StronglyTypedIdDefaultsAttribute.verified.txt @@ -27,9 +27,12 @@ namespace StronglyTypedIds /// Set the default template to use for strongly typed IDs /// /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) + /// The names of additional custom templates to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template, params string[] templateNames) { - Template = template; } /// @@ -41,18 +44,18 @@ namespace StronglyTypedIds /// public StronglyTypedIdDefaultsAttribute(string templateName) { - TemplateName = templateName; } /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. + /// Set the default template to use for strongly typed IDs /// - public string? TemplateName { get; } + /// The name of the template to use to generate the ID. + /// Templates must be added to the project using the format NAME.typedid, + /// where NAME is the name of the template passed in . + /// + public StronglyTypedIdDefaultsAttribute(string templateName, params string[] templateNames) + { + } } } #endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt deleted file mode 100644 index 65833f742..000000000 --- a/test/StronglyTypedIds.Tests/Snapshots/NoGeneratedIds.verified.txt +++ /dev/null @@ -1,153 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Place on partial structs to make the type a strongly-typed ID - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdAttribute : global::System.Attribute - { - /// - /// Make the struct a strongly typed ID. - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Make the struct a strongly typed ID. - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// Make the struct a strongly typed ID, using the default template - /// - public StronglyTypedIdAttribute() - { - } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -namespace StronglyTypedIds -{ - /// - /// Used to control the default strongly typed ID values. Apply to an assembly using - /// [assembly:StronglyTypedIdDefaults(Template.Int)] for example - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] - [global::System.Diagnostics.Conditional("STRONGLY_TYPED_ID_USAGES")] - internal sealed class StronglyTypedIdDefaultsAttribute : global::System.Attribute - { - /// - /// Set the default template to use for strongly typed IDs - /// - /// The built-in template to use to generate the ID. - public StronglyTypedIdDefaultsAttribute(global::StronglyTypedIds.Template template) - { - Template = template; - } - - /// - /// Set the default template to use for strongly typed IDs - /// - /// The name of the template to use to generate the ID. - /// Templates must be added to the project using the format NAME.typedid, - /// where NAME is the name of the template passed in . - /// - public StronglyTypedIdDefaultsAttribute(string templateName) - { - TemplateName = templateName; - } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public global::StronglyTypedIds.Template? Template { get; } - - /// - /// The default template to use to generate the strongly-typed ID value. - /// - public string? TemplateName { get; } - } -} -#endif -//------------------------------------------------------------------------------ -// -// This code was generated by the StronglyTypedId source generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -#pragma warning disable 1591 // publicly visible type or member must be documented - -#nullable enable - -#if STRONGLY_TYPED_ID_EMBED_ATTRIBUTES - -using System; - -namespace StronglyTypedIds -{ - /// - /// The built-in template to use to generate the strongly-typed ID - /// - internal enum Template - { - Guid, - Int, - String, - Long, - } -} -#endif \ No newline at end of file diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs index f5d7f67de..56d3c8986 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs +++ b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs @@ -35,6 +35,7 @@ public partial struct MyId {}"; [Theory] [InlineData("")] [InlineData("Template.Guid")] + [InlineData("template: Template.Guid")] public Task CanGenerateIdInNamespace(string template) { var input = $$""" @@ -54,14 +55,16 @@ public partial struct MyId {} .UseDirectory("Snapshots"); } - [Fact] - public Task CanGenerateNonDefaultIdInNamespace() + [Theory] + [InlineData("Template.Int")] + [InlineData("template: Template.Int")] + public Task CanGenerateNonDefaultIdInNamespace(string template) { var input = $$""" using StronglyTypedIds; namespace SomeNamespace { - [StronglyTypedId(Template.Int)] + [StronglyTypedId({{template}})] public partial struct MyId {} } """; @@ -74,14 +77,16 @@ public partial struct MyId {} .UseDirectory("Snapshots"); } - [Fact] - public Task CanGenerateForCustomTemplate() + [Theory] + [InlineData("\"newid-full\"")] + [InlineData("templateNames: \"newid-full\"")] + public Task CanGenerateForCustomTemplate(string templateName) { - var input = """ + var input = $$""" using StronglyTypedIds; namespace SomeNamespace { - [StronglyTypedId("newid-full")] + [StronglyTypedId({{templateName}})] public partial struct MyId {} } """; @@ -183,12 +188,14 @@ public partial struct MyId {} .UseDirectory("Snapshots"); } - [Fact] - public Task CanOverrideDefaultsWithTemplateUsingGlobalAttribute() + [Theory] + [InlineData("Template.Int")] + [InlineData("template: Template.Int")] + public Task CanOverrideDefaultsWithTemplateUsingGlobalAttribute(string template) { - const string input = """ + var input = $$""" using StronglyTypedIds; - [assembly:StronglyTypedIdDefaults(Template.Int)] + [assembly:StronglyTypedIdDefaults({{template}})] [StronglyTypedId] public partial struct MyId {} @@ -199,15 +206,18 @@ public partial struct MyId {} Assert.Empty(diagnostics); return Verifier.Verify(output) + .DisableRequireUniquePrefix() .UseDirectory("Snapshots"); } - [Fact] - public Task CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute() + [Theory] + [InlineData("\"newid-full\"")] + [InlineData("templateName: \"newid-full\"")] + public Task CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute(string templateNames) { - const string input = """ + var input = $$""" using StronglyTypedIds; - [assembly:StronglyTypedIdDefaults("newid-full")] + [assembly:StronglyTypedIdDefaults({{templateNames}})] [StronglyTypedId] public partial struct MyId {} @@ -218,6 +228,7 @@ public partial struct MyId {} Assert.Empty(diagnostics); return Verifier.Verify(output) + .DisableRequireUniquePrefix() .UseDirectory("Snapshots"); } From 6291d0e35cce19bd9cffab0366a9545dea28055c Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 10 Nov 2023 19:48:27 +0000 Subject: [PATCH 26/47] Add unit tests for multiple templates --- .../SourceGenerationHelper.cs | 2 +- ...eMultipleTemplatesWithBuiltIn.verified.txt | 261 ++++++++++++++++++ ...ltipleTemplatesWithoutBuiltIn.verified.txt | 47 ++++ .../StronglyTypedIdGeneratorTests.cs | 66 +++++ 4 files changed, 375 insertions(+), 1 deletion(-) create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt create mode 100644 test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt diff --git a/src/StronglyTypedIds/SourceGenerationHelper.cs b/src/StronglyTypedIds/SourceGenerationHelper.cs index ab58f39ca..d0b4da9b9 100644 --- a/src/StronglyTypedIds/SourceGenerationHelper.cs +++ b/src/StronglyTypedIds/SourceGenerationHelper.cs @@ -103,7 +103,7 @@ internal static string CreateSourceName(StringBuilder sb, string nameSpace, Pare sb.Append(name); if (!string.IsNullOrEmpty(template)) { - sb.Append(template).Append('.'); + sb.Append('.').Append(template); } return sb.Append(".g.cs").ToString(); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt new file mode 100644 index 000000000..381d961be --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt @@ -0,0 +1,261 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + partial struct MyId + { + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new MyId(value), + mappingHints + ) { } + } + } + +.MyId.guid-efcore.g.cs//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + partial struct MyId + { + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, MyId value) + { + parameter.Value = value.Value; + } + } + +.MyId.guid-dapper.g.cs//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + [global::System.ComponentModel.TypeConverter(typeof(MyIdTypeConverter))] + [global::System.Text.Json.Serialization.JsonConverter(typeof(MyIdSystemTextJsonConverter))] + partial struct MyId : +#if NET6_0_OR_GREATER + global::System.ISpanFormattable, +#endif +#if NET7_0_OR_GREATER + global::System.IParsable, global::System.ISpanParsable, +#endif + global::System.IComparable, global::System.IEquatable, global::System.IFormattable + { + public global::System.Guid Value { get; } + + public MyId(global::System.Guid value) + { + Value = value; + } + + public static MyId New() => new MyId(global::System.Guid.NewGuid()); + public static readonly MyId Empty = new MyId(global::System.Guid.Empty); + + /// + public bool Equals(MyId other) => this.Value.Equals(other.Value); + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is MyId other && Equals(other); + } + + public override int GetHashCode() => Value.GetHashCode(); + + public override string ToString() => Value.ToString(); + + public static bool operator ==(MyId a, MyId b) => a.Equals(b); + public static bool operator !=(MyId a, MyId b) => !(a == b); + + /// + public int CompareTo(MyId other) => Value.CompareTo(other.Value); + + class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object? ConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => base.ConvertFrom(context, culture, value), + }; + } + + public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type? sourceType) + { + return sourceType == typeof(global::System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType); + } + + public override object? ConvertTo(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Globalization.CultureInfo? culture, object? value, global::System.Type destinationType) + { + if (value is MyId idValue) + { + if (destinationType == typeof(global::System.Guid)) + { + return idValue.Value; + } + + if (destinationType == typeof(string)) + { + return idValue.Value.ToString(); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + { + public override bool CanConvert(global::System.Type typeToConvert) + => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); + + public override MyId Read(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new (reader.GetGuid()); + + public override void Write(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + +#if NET6_0_OR_GREATER + public override MyId ReadAsPropertyName(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Type typeToConvert, global::System.Text.Json.JsonSerializerOptions options) + => new(global::System.Guid.Parse(reader.GetString() ?? throw new global::System.FormatException("The string for the MyId property was null"))); + + public override void WriteAsPropertyName(global::System.Text.Json.Utf8JsonWriter writer, MyId value, global::System.Text.Json.JsonSerializerOptions options) + => writer.WritePropertyName(value.Value.ToString()); +#endif + } + + public static MyId Parse(string input) + => new(global::System.Guid.Parse(input)); + +#if NET7_0_OR_GREATER + /// + public static MyId Parse(string input, global::System.IFormatProvider? provider) + => new(global::System.Guid.Parse(input, provider)); + + /// + public static bool TryParse( + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, + global::System.IFormatProvider? provider, + out MyId result) + { + if (input is null) + { + result = default; + return false; + } + + if (global::System.Guid.TryParse(input, provider, out var guid)) + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } +#endif + + /// + public string ToString( +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + string? format, + global::System.IFormatProvider? formatProvider) + => Value.ToString(format, formatProvider); + +#if NETCOREAPP2_1_OR_GREATER + public static MyId Parse(global::System.ReadOnlySpan input) + => new(global::System.Guid.Parse(input)); +#endif + +#if NET6_0_OR_GREATER +#if NET7_0_OR_GREATER + /// +#endif + public static MyId Parse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider) +#if NET7_0_OR_GREATER + => new(global::System.Guid.Parse(input, provider)); +#else + => new(global::System.Guid.Parse(input)); +#endif + +#if NET7_0_OR_GREATER + /// +#endif + public static bool TryParse(global::System.ReadOnlySpan input, global::System.IFormatProvider? provider, out MyId result) + { +#if NET7_0_OR_GREATER + if (global::System.Guid.TryParse(input, provider, out var guid)) +#else + if (global::System.Guid.TryParse(input, out var guid)) +#endif + { + result = new(guid); + return true; + } + else + { + result = default; + return false; + } + } + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format, + global::System.IFormatProvider? provider) + => Value.TryFormat(destination, out charsWritten, format); + + /// + public bool TryFormat( + global::System.Span destination, + out int charsWritten, +#if NET7_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.StringSyntax(global::System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat)] +#endif + global::System.ReadOnlySpan format = default) + => Value.TryFormat(destination, out charsWritten, format); +#endif + } diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt new file mode 100644 index 000000000..b3c1bbca1 --- /dev/null +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt @@ -0,0 +1,47 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + partial struct MyId + { + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new MyId(value), + mappingHints + ) { } + } + } + +.MyId.guid-efcore.g.cs//------------------------------------------------------------------------------ +// +// This code was generated by the StronglyTypedId source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 // publicly visible type or member must be documented + +#nullable enable + partial struct MyId + { + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, MyId value) + { + parameter.Value = value.Value; + } + } diff --git a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs index 56d3c8986..4a4746d04 100644 --- a/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs +++ b/test/StronglyTypedIds.Tests/StronglyTypedIdGeneratorTests.cs @@ -258,5 +258,71 @@ public partial struct MyId {} return Verifier.Verify(output) .UseDirectory("Snapshots"); } + + [Theory] + [InlineData(false, "Template.Guid, \"guid-efcore\", \"guid-dapper\"")] + [InlineData(false, "template: Template.Guid, \"guid-efcore\", \"guid-dapper\"")] + [InlineData(false, "Template.Guid, templateNames: new [] {\"guid-efcore\", \"guid-dapper\"}")] + [InlineData(true, "Template.Guid, \"guid-efcore\", \"guid-dapper\"")] + [InlineData(true, "template: Template.Guid, \"guid-efcore\", \"guid-dapper\"")] + [InlineData(true, "Template.Guid, templateNames: new [] {\"guid-efcore\", \"guid-dapper\"}")] + public Task CanGenerateMultipleTemplatesWithBuiltIn(bool useDefault, string template) + { + var defaultAttr = useDefault + ? $"[assembly:StronglyTypedIdDefaults({template})]" + : string.Empty; + + var templateAttr = useDefault ? string.Empty : template; + + var input = $$""" + using StronglyTypedIds; + {{defaultAttr}} + + [StronglyTypedId({{templateAttr}})] + public partial struct MyId {} + """; + + // This only includes the last ID but that's good enough for this + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); + + Assert.Empty(diagnostics); + + return Verifier.Verify(output) + .DisableRequireUniquePrefix() + .UseDirectory("Snapshots"); + } + + [Theory] + [InlineData(false, "\"guid-efcore\", \"guid-dapper\"")] + [InlineData(false, "templateNames: new [] {\"guid-efcore\", \"guid-dapper\"}")] + [InlineData(true, "\"guid-dapper\", \"guid-efcore\"")] + [InlineData(true, "\"guid-dapper\", new [] {\"guid-efcore\"}")] + [InlineData(true, "\"guid-dapper\", templateNames: new [] {\"guid-efcore\"}")] + [InlineData(true, "templateName: \"guid-dapper\", templateNames: new [] {\"guid-efcore\"}")] + public Task CanGenerateMultipleTemplatesWithoutBuiltIn(bool useDefault, string template) + { + var defaultAttr = useDefault + ? $"[assembly:StronglyTypedIdDefaults({template})]" + : string.Empty; + + var templateAttr = useDefault ? string.Empty : template; + + var input = $$""" + using StronglyTypedIds; + {{defaultAttr}} + + [StronglyTypedId({{templateAttr}})] + public partial struct MyId {} + """; + + // This only includes the last ID but that's good enough for this + var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input, includeAttributes: false); + + Assert.Empty(diagnostics); + + return Verifier.Verify(output) + .DisableRequireUniquePrefix() + .UseDirectory("Snapshots"); + } } } \ No newline at end of file From fc32ea973bffeb00f65f525b83f0034b5911f059 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 10 Nov 2023 20:16:50 +0000 Subject: [PATCH 27/47] Fix StringBuilder re-use bug --- .../SourceGenerationHelper.cs | 10 +- .../StronglyTypedIdGenerator.cs | 130 +++++++++--------- ...eMultipleTemplatesWithBuiltIn.verified.txt | 15 +- ...ltipleTemplatesWithoutBuiltIn.verified.txt | 13 +- 4 files changed, 98 insertions(+), 70 deletions(-) diff --git a/src/StronglyTypedIds/SourceGenerationHelper.cs b/src/StronglyTypedIds/SourceGenerationHelper.cs index d0b4da9b9..af784f95a 100644 --- a/src/StronglyTypedIds/SourceGenerationHelper.cs +++ b/src/StronglyTypedIds/SourceGenerationHelper.cs @@ -22,7 +22,15 @@ public static string CreateId( var parentsCount = 0; - sb ??= new StringBuilder(); + if (sb is null) + { + sb = new StringBuilder(); + } + else + { + sb.Clear(); + } + sb.Append(EmbeddedSources.AutoGeneratedHeader); if (hasNamespace) diff --git a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs index b77f18686..4bb290537 100644 --- a/src/StronglyTypedIds/StronglyTypedIdGenerator.cs +++ b/src/StronglyTypedIds/StronglyTypedIdGenerator.cs @@ -2,7 +2,9 @@ using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Linq; using System.Text; +using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; @@ -69,69 +71,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Select((result, _) => result.Value.defaults) .Collect() .Combine(templates) - .Select((all, _) => - { - if (all.Left.IsDefaultOrEmpty) - { - // no default attributes, valid, but no content - return (EquatableArray<(string Name, string Content)>.Empty, true, null); - } - - // technically we can never have more than one `Defaults` here - // but check for it just in case - if (all.Left is {IsDefaultOrEmpty: false, Length: > 1}) - { - return (EquatableArray<(string Name, string Content)>.Empty, false, null); - } - - var defaults = all.Left[0]; - if (defaults.HasMultiple) - { - // not valid - return (EquatableArray<(string Name, string Content)>.Empty, false, null); - } - - (string, string)? builtInTemplate = null; - if (defaults.Template is { } templateId) - { - // Explicit template - builtInTemplate = (string.Empty, EmbeddedSources.GetTemplate(templateId)); - } - - var templateNames = defaults.TemplateNames.GetArray(); - if (templateNames is null or {Length: 0}) - { - if (builtInTemplate.HasValue) - { - // valid, only built-in - var template = new EquatableArray<(string Name, string Content)>(new[] {builtInTemplate.Value}); - return (template, true, (DiagnosticInfo?) null); - } - - // not valid, need something - return (EquatableArray<(string Name, string Content)>.Empty, false, null); - } - - // We have already checked for null/empty template name and flagged it as an error - if (!GetContent( - templateNames, - defaults.TemplateLocation!, - builtInTemplate.HasValue, - in all.Right, - out var contents, - out var diagnostic)) - { - return (EquatableArray<(string Name, string Content)>.Empty, false, diagnostic); - } - - if (builtInTemplate.HasValue) - { - contents[^1] = builtInTemplate.Value; - } - - // Ok, we have all the templates - return (new EquatableArray<(string Name, string Content)>(contents), true, null); - }); + .Select(ProcessDefaults); var structsWithDefaultsAndTemplates = structs .Combine(templates) @@ -140,14 +80,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.RegisterSourceOutput(structsWithDefaultsAndTemplates, static (spc, source) => Execute(source.Left.Left, source.Left.Right, source.Right, spc)); } - private static void Execute( StructToGenerate idToGenerate, ImmutableArray<(string Path, string Name, string? Content)> templates, (EquatableArray<(string Name, string Content)>, bool IsValid, DiagnosticInfo? Diagnostic) defaults, SourceProductionContext context) { - var sb = new StringBuilder(); if (defaults.Diagnostic is { } diagnostic) { // report error with the default template @@ -159,7 +97,8 @@ private static void Execute( return; } - foreach (var (name, content) in templateContents) + var sb = new StringBuilder(); + foreach (var (name, content) in templateContents.Distinct()) { var result = SourceGenerationHelper.CreateId( idToGenerate.NameSpace, @@ -180,6 +119,65 @@ private static void Execute( } } + + private static (EquatableArray<(string Name, string Content)>, bool, DiagnosticInfo?) ProcessDefaults((ImmutableArray Left, ImmutableArray<(string Path, string Name, string? Content)> Right) all, CancellationToken _) + { + if (all.Left.IsDefaultOrEmpty) + { + // no default attributes, valid, but no content + return (EquatableArray<(string Name, string Content)>.Empty, true, null); + } + + // technically we can never have more than one `Defaults` here + // but check for it just in case + if (all.Left is {IsDefaultOrEmpty: false, Length: > 1}) + { + return (EquatableArray<(string Name, string Content)>.Empty, false, null); + } + + var defaults = all.Left[0]; + if (defaults.HasMultiple) + { + // not valid + return (EquatableArray<(string Name, string Content)>.Empty, false, null); + } + + (string, string)? builtInTemplate = null; + if (defaults.Template is { } templateId) + { + // Explicit template + builtInTemplate = (string.Empty, EmbeddedSources.GetTemplate(templateId)); + } + + var templateNames = defaults.TemplateNames.GetArray(); + if (templateNames is null or {Length: 0}) + { + if (builtInTemplate.HasValue) + { + // valid, only built-in + var template = new EquatableArray<(string Name, string Content)>(new[] {builtInTemplate.Value}); + return (template, true, (DiagnosticInfo?) null); + } + + // not valid, need something + return (EquatableArray<(string Name, string Content)>.Empty, false, null); + } + + // We have already checked for null/empty template name and flagged it as an error + if (!GetContent(templateNames, defaults.TemplateLocation!, builtInTemplate.HasValue, in all.Right, out var contents, out var diagnostic)) + { + return (EquatableArray<(string Name, string Content)>.Empty, false, diagnostic); + } + + if (builtInTemplate.HasValue) + { + contents[^1] = builtInTemplate.Value; + } + + // Ok, we have all the templates + return (new EquatableArray<(string Name, string Content)>(contents), true, null); + } + private static bool TryGetTemplateContent( in StructToGenerate idToGenerate, in ImmutableArray<(string Path, string Name, string? Content)> templates, diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt index 381d961be..66add15df 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt @@ -24,7 +24,7 @@ } } -.MyId.guid-efcore.g.cs//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by the StronglyTypedId source generator // @@ -44,9 +44,20 @@ { parameter.Value = value.Value; } + + public override MyId Parse(object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyId"), + }; + } + } } -.MyId.guid-dapper.g.cs//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by the StronglyTypedId source generator // diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt index b3c1bbca1..b3cc80806 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt @@ -24,7 +24,7 @@ } } -.MyId.guid-efcore.g.cs//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by the StronglyTypedId source generator // @@ -44,4 +44,15 @@ { parameter.Value = value.Value; } + + public override MyId Parse(object value) + { + return value switch + { + global::System.Guid guidValue => new MyId(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new MyId(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to MyId"), + }; + } + } } From 1790690690a3753fcab898336de3b18faf57cf96 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 10 Nov 2023 20:55:25 +0000 Subject: [PATCH 28/47] Add missing templates --- .../guid-dapper.typedid | 11 ++++++++ .../int-dapper.typedid | 21 ++++++++++++++ .../int-efcore.typedid | 13 +++++++++ .../int-newstonsoftjson.typedid | 22 +++++++++++++++ .../long-dapper.typedid | 22 +++++++++++++++ .../long-efcore.typedid | 13 +++++++++ .../long-newtnosoftjson.typedid | 22 +++++++++++++++ .../string-dapper.typedid | 19 +++++++++++++ .../string-efcore.typedid | 13 +++++++++ .../string-newtonsoftjson.typedid | 28 +++++++++++++++++++ 10 files changed, 184 insertions(+) create mode 100644 src/StronglyTypedIds.Templates/int-dapper.typedid create mode 100644 src/StronglyTypedIds.Templates/int-efcore.typedid create mode 100644 src/StronglyTypedIds.Templates/int-newstonsoftjson.typedid create mode 100644 src/StronglyTypedIds.Templates/long-dapper.typedid create mode 100644 src/StronglyTypedIds.Templates/long-efcore.typedid create mode 100644 src/StronglyTypedIds.Templates/long-newtnosoftjson.typedid create mode 100644 src/StronglyTypedIds.Templates/string-dapper.typedid create mode 100644 src/StronglyTypedIds.Templates/string-efcore.typedid create mode 100644 src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid diff --git a/src/StronglyTypedIds.Templates/guid-dapper.typedid b/src/StronglyTypedIds.Templates/guid-dapper.typedid index d56f7d85a..0d8be2d10 100644 --- a/src/StronglyTypedIds.Templates/guid-dapper.typedid +++ b/src/StronglyTypedIds.Templates/guid-dapper.typedid @@ -6,4 +6,15 @@ { parameter.Value = value.Value; } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + global::System.Guid guidValue => new PLACEHOLDERID(guidValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && global::System.Guid.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/int-dapper.typedid b/src/StronglyTypedIds.Templates/int-dapper.typedid new file mode 100644 index 000000000..a7e53efc0 --- /dev/null +++ b/src/StronglyTypedIds.Templates/int-dapper.typedid @@ -0,0 +1,21 @@ + partial struct PLACEHOLDERID + { + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + int intValue => new PLACEHOLDERID(intValue), + long longValue when longValue < int.MaxValue => new PLACEHOLDERID((int)longValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/int-efcore.typedid b/src/StronglyTypedIds.Templates/int-efcore.typedid new file mode 100644 index 000000000..83f25403b --- /dev/null +++ b/src/StronglyTypedIds.Templates/int-efcore.typedid @@ -0,0 +1,13 @@ + partial struct PLACEHOLDERID + { + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/int-newstonsoftjson.typedid b/src/StronglyTypedIds.Templates/int-newstonsoftjson.typedid new file mode 100644 index 000000000..6d492433a --- /dev/null +++ b/src/StronglyTypedIds.Templates/int-newstonsoftjson.typedid @@ -0,0 +1,22 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID + { + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var result = serializer.Deserialize(reader); + return result.HasValue ? new PLACEHOLDERID(result.Value) : null; + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/long-dapper.typedid b/src/StronglyTypedIds.Templates/long-dapper.typedid new file mode 100644 index 000000000..226f71367 --- /dev/null +++ b/src/StronglyTypedIds.Templates/long-dapper.typedid @@ -0,0 +1,22 @@ + partial struct PLACEHOLDERID + { + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + long longValue => new PLACEHOLDERID(longValue), + int intValue => new PLACEHOLDERID(intValue), + short shortValue => new PLACEHOLDERID(shortValue), + string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new PLACEHOLDERID(result), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/long-efcore.typedid b/src/StronglyTypedIds.Templates/long-efcore.typedid new file mode 100644 index 000000000..34aa55c3c --- /dev/null +++ b/src/StronglyTypedIds.Templates/long-efcore.typedid @@ -0,0 +1,13 @@ + partial struct PLACEHOLDERID + { + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/long-newtnosoftjson.typedid b/src/StronglyTypedIds.Templates/long-newtnosoftjson.typedid new file mode 100644 index 000000000..5ae2a6394 --- /dev/null +++ b/src/StronglyTypedIds.Templates/long-newtnosoftjson.typedid @@ -0,0 +1,22 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID + { + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + var result = serializer.Deserialize(reader); + return result.HasValue ? new PLACEHOLDERID(result.Value) : null; + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/string-dapper.typedid b/src/StronglyTypedIds.Templates/string-dapper.typedid new file mode 100644 index 000000000..28b00a2c3 --- /dev/null +++ b/src/StronglyTypedIds.Templates/string-dapper.typedid @@ -0,0 +1,19 @@ + partial struct PLACEHOLDERID + { + public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + { + public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) + { + parameter.Value = value.Value; + } + + public override PLACEHOLDERID Parse(object value) + { + return value switch + { + string stringValue => new PLACEHOLDERID(stringValue), + _ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"), + }; + } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/string-efcore.typedid b/src/StronglyTypedIds.Templates/string-efcore.typedid new file mode 100644 index 000000000..2efb1eec2 --- /dev/null +++ b/src/StronglyTypedIds.Templates/string-efcore.typedid @@ -0,0 +1,13 @@ + partial struct PLACEHOLDERID + { + public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + { + public EfCoreValueConverter() : this(null) { } + public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) + : base( + id => id.Value, + value => new PLACEHOLDERID(value), + mappingHints + ) { } + } + } \ No newline at end of file diff --git a/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid new file mode 100644 index 000000000..bc09e3840 --- /dev/null +++ b/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid @@ -0,0 +1,28 @@ + [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] + partial struct PLACEHOLDERID + { + class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + { + public override bool CanConvert(global::System.Type objectType) + { + return objectType == typeof(PLACEHOLDERID); + } + + public override void WriteJson(global::Newtonsoft.Json.JsonWriter writer, object? value, global::Newtonsoft.Json.JsonSerializer serializer) + { + serializer.Serialize(writer, value is PLACEHOLDERID id ? id.Value : null); + } + + public override object? ReadJson(global::Newtonsoft.Json.JsonReader reader, global::System.Type objectType, object? existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + if (objectType == typeof(PLACEHOLDERID?)) + { + var value = serializer.Deserialize(reader); + + return value is null ? null : new PLACEHOLDERID(value); + } + + return new PLACEHOLDERID(serializer.Deserialize(reader)!); + } + } + } \ No newline at end of file From abe08f5afa09fb6b57220c9a3f9218bbb984c4aa Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 10 Nov 2023 20:55:48 +0000 Subject: [PATCH 29/47] Add guid converter templates tests --- .../DapperTypeHandlers.cs | 1 + .../Enums.cs | 3 + .../GuidIdTests.cs | 270 +++++++++++++----- 3 files changed, 207 insertions(+), 67 deletions(-) diff --git a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs index a223b2f0e..5fbff4f3e 100644 --- a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs +++ b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs @@ -10,6 +10,7 @@ public static class DapperTypeHandlers public static void AddHandlers() { SqlMapper.AddTypeHandler(new ConvertersGuidId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new ConvertersGuidId2.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersIntId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersLongId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersStringId.DapperTypeHandler()); diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index 3e8c7dbd1..dfa6f0a99 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -16,6 +16,9 @@ partial struct GuidId1 { } [StronglyTypedId("guid-full")] partial struct ConvertersGuidId { } +[StronglyTypedId(Template.Guid, "guid-efcore", "guid-dapper", "guid-newtonsoftjson")] +partial struct ConvertersGuidId2 { } + [StronglyTypedId(Template.Guid)] public partial struct GuidId2 { } diff --git a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs index 3b346d482..e9966328c 100644 --- a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs @@ -32,7 +32,6 @@ public void EmptyValueIsEmpty() Assert.Equal(GuidId1.Empty.Value, Guid.Empty); } - [Fact] public void DifferentValuesAreUnequal() { @@ -144,6 +143,87 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() } #endif + [Fact] + public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() + { + var foo = GuidId1.New(); + + var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); + + var expected = $"\"{foo.Value}\""; + + Assert.Equal(expected, serialized); + } + + [Theory] + [InlineData("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")] + public void TypeConverter_CanConvertToAndFrom(string value) + { + var converter = TypeDescriptor.GetConverter(typeof(GuidId1)); + var id = converter.ConvertFrom(value); + Assert.IsType(id); + Assert.Equal(new GuidId1(Guid.Parse(value)), id); + + var reconverted = converter.ConvertTo(id, value.GetType()); + Assert.Equal(value, reconverted); + } + + [Fact] + public void CanCompareDefaults() + { + GuidId1 original = default; + var other = GuidId1.Empty; + + var compare1 = original.CompareTo(other); + var compare2 = other.CompareTo(original); + Assert.Equal(compare1, -compare2); + } + + [Fact] + public void CanEquateDefaults() + { + GuidId1 original = default; + var other = GuidId1.Empty; + + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); + + Assert.Equal(equals1, equals2); + } + + [Fact] + public void ImplementsInterfaces() + { + Assert.IsAssignableFrom>(GuidId1.Empty); + Assert.IsAssignableFrom>(GuidId1.Empty); + Assert.IsAssignableFrom(GuidId1.Empty); + +#pragma warning disable CS0183 +#pragma warning disable 184 + Assert.True(GuidId1.Empty is IComparable); + Assert.True(GuidId1.Empty is IEquatable); +#pragma warning restore 184 +#pragma warning restore CS0183 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(GuidId1.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs(Guid.NewGuid().ToString()); + ParseSpan(Guid.NewGuid().ToString().AsSpan()); + + T ParseAs(string s) where T: IParsable { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T: ISpanParsable { + return T.Parse(s, null); + } +#endif + } + +#region ConvertersGuidId [Fact] public void CanDeserializeFromGuid_WithNewtonsoftJsonProvider() { @@ -183,18 +263,6 @@ public void CanSerializeToGuid_WithBothJsonConverters() Assert.Equal(serializedFoo2, serializedGuid2); } - [Fact] - public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() - { - var foo = GuidId1.New(); - - var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); - - var expected = $"\"{foo.Value}\""; - - Assert.Equal(expected, serialized); - } - [Fact] public void WhenEfCoreValueConverterUsesValueConverter() { @@ -231,77 +299,112 @@ public async Task WhenDapperValueConverterUsesValueConverter() Assert.Equal(value, new ConvertersGuidId(Guid.Parse("5640dad4-862a-4738-9e3c-c76dc227eb66"))); } - [Theory] - [InlineData("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")] - public void TypeConverter_CanConvertToAndFrom(string value) +#if NET6_0_OR_GREATER + [Fact] + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() { - var converter = TypeDescriptor.GetConverter(typeof(GuidId1)); - var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new GuidId1(Guid.Parse(value)), id); + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); - var reconverted = converter.ConvertTo(id, value.GetType()); - Assert.Equal(value, reconverted); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add( + new TestEntity { Id = ConvertersGuidId.New() }); + context.SaveChanges(); + } + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + Assert.Single(all); + } } +#endif +#endregion +#region ConvertersGuidId2 [Fact] - public void CanCompareDefaults() + public void CanDeserializeFromGuid_WithMultiTemplates_WithNewtonsoftJsonProvider() { - GuidId1 original = default; - var other = GuidId1.Empty; - - var compare1 = original.CompareTo(other); - var compare2 = other.CompareTo(original); - Assert.Equal(compare1, -compare2); + var value = Guid.NewGuid(); + var foo = new ConvertersGuidId2(value); + var serializedGuid = NewtonsoftJsonSerializer.SerializeObject(value); + + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedGuid); + + Assert.Equal(foo, deserializedFoo); } [Fact] - public void CanEquateDefaults() + public void CanSerializeToNullable_WithMultiTemplates_WithNewtonsoftJsonProvider() { - GuidId1 original = default; - var other = GuidId1.Empty; - - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); - - Assert.Equal(equals1, equals2); + var entity = new EntityWithNullableId2 { Id = null }; + + var json = NewtonsoftJsonSerializer.SerializeObject(entity); + var deserialize = NewtonsoftJsonSerializer.DeserializeObject(json); + + Assert.NotNull(deserialize); + Assert.Null(deserialize.Id); } [Fact] - public void ImplementsInterfaces() + public void CanSerializeToGuid_WithMultiTemplates_WithBothJsonConverters() { - Assert.IsAssignableFrom>(GuidId1.Empty); - Assert.IsAssignableFrom>(GuidId1.Empty); - Assert.IsAssignableFrom(GuidId1.Empty); - -#pragma warning disable CS0183 -#pragma warning disable 184 - Assert.True(GuidId1.Empty is IComparable); - Assert.True(GuidId1.Empty is IEquatable); -#pragma warning restore 184 -#pragma warning restore CS0183 - -#if NET6_0_OR_GREATER - Assert.IsAssignableFrom(GuidId1.Empty); -#endif -#if NET7_0_OR_GREATER - // doesn't compile if doesn't implement it - ParseAs(Guid.NewGuid().ToString()); - ParseSpan(Guid.NewGuid().ToString().AsSpan()); + var foo = ConvertersGuidId2.New(); + + var serializedFoo1 = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedGuid1 = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + var serializedFoo2 = SystemTextJsonSerializer.Serialize(foo); + var serializedGuid2 = SystemTextJsonSerializer.Serialize(foo.Value); + + Assert.Equal(serializedFoo1, serializedGuid1); + Assert.Equal(serializedFoo2, serializedGuid2); + } - T ParseAs(string s) where T: IParsable { - return T.Parse(s, null); + [Fact] + public void WhenEfCore_WithMultiTemplates_ValueConverterUsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new TestDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities2.Add( + new TestEntity2 { Id = ConvertersGuidId2.New() }); + context.SaveChanges(); } - - T ParseSpan(ReadOnlySpan s) where T: ISpanParsable { - return T.Parse(s, null); + using (var context = new TestDbContext(options)) + { + var all = context.Entities2.ToList(); + Assert.Single(all); } -#endif + } + + [Fact] + public async Task WhenDapperValueConverter_WithMultiTemplates_UsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + await connection.OpenAsync(); + + var results = await connection.QueryAsync("SELECT '5640dad4-862a-4738-9e3c-c76dc227eb66'"); + + var value = Assert.Single(results); + Assert.Equal(value, new ConvertersGuidId2(Guid.Parse("5640dad4-862a-4738-9e3c-c76dc227eb66"))); } #if NET6_0_OR_GREATER [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + public void WhenConventionBasedEfCore_WithMultiTemplates_ValueConverterUsesValueConverter() { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -313,20 +416,23 @@ public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() using (var context = new ConventionsDbContext(options)) { context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity { Id = ConvertersGuidId.New() }); + context.Entities2.Add( + new TestEntity2 { Id = ConvertersGuidId2.New() }); context.SaveChanges(); } using (var context = new ConventionsDbContext(options)) { - var all = context.Entities.ToList(); + var all = context.Entities2.ToList(); Assert.Single(all); } } - +#endif +#endregion +#if NET6_0_OR_GREATER internal class ConventionsDbContext : DbContext { public DbSet Entities { get; set; } + public DbSet Entities2 { get; set; } public ConventionsDbContext(DbContextOptions options) : base(options) { @@ -337,6 +443,9 @@ protected override void ConfigureConventions(ModelConfigurationBuilder configura configurationBuilder .Properties() .HaveConversion(); + configurationBuilder + .Properties() + .HaveConversion(); } protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -348,6 +457,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Property(x => x.Id) .ValueGeneratedNever(); }); + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); } } #endif @@ -355,6 +471,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) internal class TestDbContext : DbContext { public DbSet Entities { get; set; } + public DbSet Entities2 { get; set; } public TestDbContext(DbContextOptions options) : base(options) { @@ -370,6 +487,15 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasConversion(new ConvertersGuidId.EfCoreValueConverter()) .ValueGeneratedNever(); }); + + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .HasConversion(new ConvertersGuidId2.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); } } @@ -387,5 +513,15 @@ internal class TypeWithDictionaryKeys { public Dictionary Values { get; set; } } + + internal class TestEntity2 + { + public ConvertersGuidId2 Id { get; set; } + } + + internal class EntityWithNullableId2 + { + public ConvertersGuidId2? Id { get; set; } + } } } \ No newline at end of file From a3a402ce2b7a7547db740691a6a186ebd2e03b2a Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 10 Nov 2023 21:19:33 +0000 Subject: [PATCH 30/47] Add LongId tests --- .../DapperTypeHandlers.cs | 2 + .../Enums.cs | 6 + .../IntIdTests.cs | 306 +++++++++++++---- .../LongIdTests.cs | 313 +++++++++++++----- 4 files changed, 471 insertions(+), 156 deletions(-) diff --git a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs index 5fbff4f3e..ec80cda4c 100644 --- a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs +++ b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs @@ -12,7 +12,9 @@ public static void AddHandlers() SqlMapper.AddTypeHandler(new ConvertersGuidId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersGuidId2.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersIntId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new ConvertersIntId2.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersLongId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new ConvertersLongId2.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersStringId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new NullableStringId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new NewIdId1.DapperTypeHandler()); diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index dfa6f0a99..8b8a67571 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -28,12 +28,18 @@ partial struct IntId { } [StronglyTypedId("int-full")] partial struct ConvertersIntId { } +[StronglyTypedId(Template.Int, "int-efcore", "int-dapper", "int-newtonsoftjson")] +partial struct ConvertersIntId2 { } + [StronglyTypedId(Template.Long)] partial struct LongId { } [StronglyTypedId("long-full")] partial struct ConvertersLongId { } +[StronglyTypedId(Template.Long, "long-efcore", "long-dapper", "long-newtonsoftjson")] +partial struct ConvertersLongId2 { } + [StronglyTypedId("newid-full")] partial struct NewIdId1 { } diff --git a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs index 6da642457..b930c3120 100644 --- a/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/IntIdTests.cs @@ -66,17 +66,6 @@ public void DifferentTypesAreUnequal() Assert.NotEqual((object) bar, (object) foo); } - [Fact] - public void CanSerializeToInt_WithNewtonsoftJsonProvider() - { - var foo = new ConvertersIntId(123); - - var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedInt = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - Assert.Equal(serializedFoo, serializedInt); - } - [Fact] public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() { @@ -89,17 +78,6 @@ public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() Assert.Null(deserialize.Id); } - [Fact] - public void CanSerializeToInt_WithSystemTextJsonProvider() - { - var foo = new ConvertersIntId(123); - - var serializedFoo = SystemTextJsonSerializer.Serialize(foo); - var serializedInt = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo, serializedInt); - } - #if NET6_0_OR_GREATER [Fact] public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() @@ -134,6 +112,98 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() } #endif + [Fact] + public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() + { + var foo = new IntId(123); + + var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); + + var expected = $"\"{foo.Value}\""; + + Assert.Equal(expected, serialized); + } + + [Fact] + public void CanCompareDefaults() + { + IntId original = default; + var other = IntId.Empty; + + var compare1 = original.CompareTo(other); + var compare2 = other.CompareTo(original); + Assert.Equal(compare1, -compare2); + } + + [Fact] + public void CanEquateDefaults() + { + IntId original = default; + var other = IntId.Empty; + + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); + + Assert.Equal(equals1, equals2); + } + + [Fact] + public void ImplementsInterfaces() + { + Assert.IsAssignableFrom>(IntId.Empty); + Assert.IsAssignableFrom>(IntId.Empty); + Assert.IsAssignableFrom(IntId.Empty); + +#pragma warning disable CS0183 +#pragma warning disable 184 + Assert.True(IntId.Empty is IComparable); + Assert.True(IntId.Empty is IEquatable); +#pragma warning restore 184 +#pragma warning restore CS0183 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(IntId.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs("123"); + ParseSpan("123".AsSpan()); + + T ParseAs(string s) where T : IParsable + { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + { + return T.Parse(s, null); + } +#endif + } + +#region ConvertersIntId + [Fact] + public void CanSerializeToInt_WithNewtonsoftJsonProvider() + { + var foo = new ConvertersIntId(123); + + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedInt = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + Assert.Equal(serializedFoo, serializedInt); + } + + [Fact] + public void CanSerializeToInt_WithSystemTextJsonProvider() + { + var foo = new ConvertersIntId(123); + + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedInt = SystemTextJsonSerializer.Serialize(foo.Value); + + Assert.Equal(serializedFoo, serializedInt); + } + [Fact] public void CanDeserializeFromInt_WithNewtonsoftJsonProvider() { @@ -158,18 +228,6 @@ public void CanDeserializeFromInt_WithSystemTextJsonProvider() Assert.Equal(foo, deserializedFoo); } - [Fact] - public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() - { - var foo = new IntId(123); - - var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); - - var expected = $"\"{foo.Value}\""; - - Assert.Equal(expected, serialized); - } - [Fact] public void WhenEfCoreValueConverterUsesValueConverter() { @@ -222,66 +280,137 @@ public void TypeConverter_CanConvertToAndFrom(object value) Assert.Equal(value, reconverted); } +#if NET6_0_OR_GREATER [Fact] - public void CanCompareDefaults() + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() { - IntId original = default; - var other = IntId.Empty; + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); - var compare1 = original.CompareTo(other); - var compare2 = other.CompareTo(original); - Assert.Equal(compare1, -compare2); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add( + new TestEntity {Id = new ConvertersIntId(123)}); + context.SaveChanges(); + } + + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + Assert.Single(all); + } } +#endif +#endregion + +#region ConvertersIntId22 [Fact] - public void CanEquateDefaults() + public void CanSerializeToInt_WithMultiTemplates_WithNewtonsoftJsonProvider() { - IntId original = default; - var other = IntId.Empty; + var foo = new ConvertersIntId2(123); - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedInt = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - Assert.Equal(equals1, equals2); + Assert.Equal(serializedFoo, serializedInt); } [Fact] - public void ImplementsInterfaces() + public void CanSerializeToInt_WithMultiTemplates_WithSystemTextJsonProvider() { - Assert.IsAssignableFrom>(IntId.Empty); - Assert.IsAssignableFrom>(IntId.Empty); - Assert.IsAssignableFrom(IntId.Empty); + var foo = new ConvertersIntId2(123); -#pragma warning disable CS0183 -#pragma warning disable 184 - Assert.True(IntId.Empty is IComparable); - Assert.True(IntId.Empty is IEquatable); -#pragma warning restore 184 -#pragma warning restore CS0183 + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedInt = SystemTextJsonSerializer.Serialize(foo.Value); -#if NET6_0_OR_GREATER - Assert.IsAssignableFrom(IntId.Empty); -#endif -#if NET7_0_OR_GREATER - // doesn't compile if doesn't implement it - ParseAs("123"); - ParseSpan("123".AsSpan()); + Assert.Equal(serializedFoo, serializedInt); + } - T ParseAs(string s) where T : IParsable + [Fact] + public void CanDeserializeFromInt_WithMultiTemplates_WithNewtonsoftJsonProvider() + { + var value = 123; + var foo = new ConvertersIntId2(value); + var serializedInt = NewtonsoftJsonSerializer.SerializeObject(value); + + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedInt); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void CanDeserializeFromInt_WithMultiTemplates_WithSystemTextJsonProvider() + { + var value = 123; + var foo = new ConvertersIntId2(value); + var serializedInt = SystemTextJsonSerializer.Serialize(value); + + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedInt); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void WhenEfCoreValueConverter_WithMultiTemplates_UsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity2 {Id = new ConvertersIntId2(123)}; + using (var context = new TestDbContext(options)) { - return T.Parse(s, null); + context.Database.EnsureCreated(); + context.Entities2.Add(original); + context.SaveChanges(); } - T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + using (var context = new TestDbContext(options)) { - return T.Parse(s, null); + var all = context.Entities2.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); } -#endif + } + + [Fact] + public async Task WhenDapperValueConverter_WithMultiTemplates_UsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + await connection.OpenAsync(); + + var results = await connection.QueryAsync("SELECT 123"); + + var value = Assert.Single(results); + Assert.Equal(new ConvertersIntId2(123), value); + } + + [Theory] + [InlineData(123)] + [InlineData("123")] + public void TypeConverter_WithMultiTemplates_CanConvertToAndFrom(object value) + { + var converter = TypeDescriptor.GetConverter(typeof(ConvertersIntId2)); + var id = converter.ConvertFrom(value); + Assert.IsType(id); + Assert.Equal(new ConvertersIntId2(123), id); + + var reconverted = converter.ConvertTo(id, value.GetType()); + Assert.Equal(value, reconverted); } #if NET6_0_OR_GREATER [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + public void WhenConventionBasedEfCoreValueConverter_WithMultiTemplates_UsesValueConverter() { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -293,21 +422,25 @@ public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() using (var context = new ConventionsDbContext(options)) { context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity {Id = new ConvertersIntId(123)}); + context.Entities2.Add( + new TestEntity2 {Id = new ConvertersIntId2(123)}); context.SaveChanges(); } using (var context = new ConventionsDbContext(options)) { - var all = context.Entities.ToList(); + var all = context.Entities2.ToList(); Assert.Single(all); } } +#endif +#endregion +#if NET6_0_OR_GREATER internal class ConventionsDbContext : DbContext { public DbSet Entities { get; set; } + public DbSet Entities2 { get; set; } public ConventionsDbContext(DbContextOptions options) : base(options) { @@ -318,6 +451,9 @@ protected override void ConfigureConventions(ModelConfigurationBuilder configura configurationBuilder .Properties() .HaveConversion(); + configurationBuilder + .Properties() + .HaveConversion(); } protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -329,6 +465,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Property(x => x.Id) .ValueGeneratedNever(); }); + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); } } #endif @@ -336,6 +479,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) internal class TestDbContext : DbContext { public DbSet Entities { get; set; } + public DbSet Entities2 { get; set; } public TestDbContext(DbContextOptions options) : base(options) { @@ -351,6 +495,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasConversion(new ConvertersIntId.EfCoreValueConverter()) .ValueGeneratedNever(); }); + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .HasConversion(new ConvertersIntId2.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); } } @@ -364,6 +516,16 @@ internal class EntityWithNullableId public ConvertersIntId? Id { get; set; } } + internal class TestEntity2 + { + public ConvertersIntId2 Id { get; set; } + } + + internal class EntityWithNullableId2 + { + public ConvertersIntId2? Id { get; set; } + } + internal class TypeWithDictionaryKeys { public Dictionary Values { get; set; } diff --git a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs index 617e2d7df..0c0787312 100644 --- a/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/LongIdTests.cs @@ -32,7 +32,6 @@ public void EmptyValueIsEmpty() Assert.Equal(0, LongId.Empty.Value); } - [Fact] public void DifferentValuesAreUnequal() { @@ -66,17 +65,6 @@ public void DifferentTypesAreUnequal() Assert.NotEqual((object)bar, (object)foo); } - [Fact] - public void CanSerializeToLong_WithNewtonsoftJsonProvider() - { - var foo = new ConvertersLongId(123); - - var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedLong = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - Assert.Equal(serializedFoo, serializedLong); - } - [Fact] public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() { @@ -89,17 +77,6 @@ public void CanSerializeToNullableInt_WithNewtonsoftJsonProvider() Assert.Null(deserialize.Id); } - [Fact] - public void CanSerializeToLong_WithSystemTextJsonProvider() - { - var foo = new ConvertersLongId(123L); - - var serializedFoo = SystemTextJsonSerializer.Serialize(foo); - var serializedLong = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo, serializedLong); - } - #if NET6_0_OR_GREATER [Fact] public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() @@ -134,6 +111,111 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() } #endif + [Fact] + public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() + { + var foo = new LongId(123); + + var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); + + var expected = $"\"{foo.Value}\""; + + Assert.Equal(expected, serialized); + } + + [Theory] + [InlineData(123L)] + [InlineData("123")] + public void TypeConverter_CanConvertToAndFrom(object value) + { + var converter = TypeDescriptor.GetConverter(typeof(LongId)); + var id = converter.ConvertFrom(value); + Assert.IsType(id); + Assert.Equal(new LongId(123), id); + + var reconverted = converter.ConvertTo(id, value.GetType()); + Assert.Equal(value, reconverted); + } + + [Fact] + public void CanCompareDefaults() + { + LongId original = default; + var other = LongId.Empty; + + var compare1 = original.CompareTo(other); + var compare2 = other.CompareTo(original); + Assert.Equal(compare1, -compare2); + } + + [Fact] + public void CanEquateDefaults() + { + LongId original = default; + var other = LongId.Empty; + + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); + + Assert.Equal(equals1, equals2); + } + + [Fact] + public void ImplementsInterfaces() + { + Assert.IsAssignableFrom>(LongId.Empty); + Assert.IsAssignableFrom>(LongId.Empty); + +#pragma warning disable 184 +#pragma warning disable CS0183 + Assert.True(LongId.Empty is IComparable); + Assert.True(LongId.Empty is IEquatable); +#pragma warning restore CS0183 +#pragma warning restore 184 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(LongId.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs("123"); + ParseSpan("123".AsSpan()); + + T ParseAs(string s) where T : IParsable + { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + { + return T.Parse(s, null); + } +#endif + } + +#region ConvertersLongId + [Fact] + public void CanSerializeToLong_WithNewtonsoftJsonProvider() + { + var foo = new ConvertersLongId(123); + + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedLong = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + Assert.Equal(serializedFoo, serializedLong); + } + + [Fact] + public void CanSerializeToLong_WithSystemTextJsonProvider() + { + var foo = new ConvertersLongId(123L); + + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedLong = SystemTextJsonSerializer.Serialize(foo.Value); + + Assert.Equal(serializedFoo, serializedLong); + } + [Fact] public void CanDeserializeFromLong_WithNewtonsoftJsonProvider() { @@ -158,18 +240,6 @@ public void CanDeserializeFromLong_WithSystemTextJsonProvider() Assert.Equal(foo, deserializedFoo); } - [Fact] - public void WhenNoJsonConverter_NewtonsoftSerializesWithoutValueProperty() - { - var foo = new LongId(123); - - var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); - - var expected = $"\"{foo.Value}\""; - - Assert.Equal(expected, serialized); - } - [Fact] public void WhenEfCoreValueConverterUsesValueConverter() { @@ -208,80 +278,122 @@ public async Task WhenDapperValueConverterUsesValueConverter() Assert.Equal(value, new ConvertersLongId(123)); } - [Theory] - [InlineData(123L)] - [InlineData("123")] - public void TypeConverter_CanConvertToAndFrom(object value) +#if NET6_0_OR_GREATER + [Fact] + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() { - var converter = TypeDescriptor.GetConverter(typeof(LongId)); - var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new LongId(123), id); + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); - var reconverted = converter.ConvertTo(id, value.GetType()); - Assert.Equal(value, reconverted); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add( + new TestEntity { Id = new ConvertersLongId(123) }); + context.SaveChanges(); + } + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + Assert.Single(all); + } } +#endif +#endregion + +#region ConvertersLongId2 [Fact] - public void CanCompareDefaults() + public void CanSerializeToLong_WithMultiTemplates_WithNewtonsoftJsonProvider() { - LongId original = default; - var other = LongId.Empty; + var foo = new ConvertersLongId2(123); - var compare1 = original.CompareTo(other); - var compare2 = other.CompareTo(original); - Assert.Equal(compare1, -compare2); + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedLong = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + Assert.Equal(serializedFoo, serializedLong); } [Fact] - public void CanEquateDefaults() + public void CanSerializeToLong_WithMultiTemplates_WithSystemTextJsonProvider() { - LongId original = default; - var other = LongId.Empty; + var foo = new ConvertersLongId2(123L); - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedLong = SystemTextJsonSerializer.Serialize(foo.Value); - Assert.Equal(equals1, equals2); + Assert.Equal(serializedFoo, serializedLong); } [Fact] - public void ImplementsInterfaces() + public void CanDeserializeFromLong_WithMultiTemplates_WithNewtonsoftJsonProvider() { - Assert.IsAssignableFrom>(LongId.Empty); - Assert.IsAssignableFrom>(LongId.Empty); + var value = 123L; + var foo = new ConvertersLongId2(value); + var serializedLong = NewtonsoftJsonSerializer.SerializeObject(value); -#pragma warning disable 184 -#pragma warning disable CS0183 - Assert.True(LongId.Empty is IComparable); - Assert.True(LongId.Empty is IEquatable); -#pragma warning restore CS0183 -#pragma warning restore 184 - -#if NET6_0_OR_GREATER - Assert.IsAssignableFrom(LongId.Empty); -#endif -#if NET7_0_OR_GREATER - // doesn't compile if doesn't implement it - ParseAs("123"); - ParseSpan("123".AsSpan()); + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedLong); - T ParseAs(string s) where T : IParsable + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void CanDeserializeFromLong_WithMultiTemplates_WithSystemTextJsonProvider() + { + var value = 123L; + var foo = new ConvertersLongId2(value); + var serializedLong = SystemTextJsonSerializer.Serialize(value); + + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedLong); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void WhenEfCoreValueConverter_WithMultiTemplates_UsesValueConverter() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity2 { Id = new ConvertersLongId2(123) }; + using (var context = new TestDbContext(options)) { - return T.Parse(s, null); + context.Database.EnsureCreated(); + context.Entities2.Add(original); + context.SaveChanges(); } - T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + using (var context = new TestDbContext(options)) { - return T.Parse(s, null); + var all = context.Entities2.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); } -#endif } + [Fact] + public async Task WhenDapperValueConverter_WithMultiTemplates_UsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + await connection.OpenAsync(); + + var results = await connection.QueryAsync("SELECT 123"); + + var value = Assert.Single(results); + Assert.Equal(value, new ConvertersLongId2(123)); + } #if NET6_0_OR_GREATER [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + public void WhenConventionBasedEfCoreValueConverter_WithMultiTemplates_UsesValueConverter() { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -293,20 +405,24 @@ public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() using (var context = new ConventionsDbContext(options)) { context.Database.EnsureCreated(); - context.Entities.Add( - new TestEntity { Id = new ConvertersLongId(123) }); + context.Entities2.Add( + new TestEntity2 { Id = new ConvertersLongId2(123) }); context.SaveChanges(); } using (var context = new ConventionsDbContext(options)) { - var all = context.Entities.ToList(); + var all = context.Entities2.ToList(); Assert.Single(all); } } - +#endif +#endregion + +#if NET6_0_OR_GREATER internal class ConventionsDbContext : DbContext { public DbSet Entities { get; set; } + public DbSet Entities2 { get; set; } public ConventionsDbContext(DbContextOptions options) : base(options) { @@ -317,6 +433,9 @@ protected override void ConfigureConventions(ModelConfigurationBuilder configura configurationBuilder .Properties() .HaveConversion(); + configurationBuilder + .Properties() + .HaveConversion(); } protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -328,6 +447,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Property(x => x.Id) .ValueGeneratedNever(); }); + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); } } #endif @@ -335,6 +461,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) internal class TestDbContext : DbContext { public DbSet Entities { get; set; } + public DbSet Entities2 { get; set; } public TestDbContext(DbContextOptions options) : base(options) { @@ -350,6 +477,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasConversion(new ConvertersLongId.EfCoreValueConverter()) .ValueGeneratedNever(); }); + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .HasConversion(new ConvertersLongId2.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); } } @@ -363,6 +498,16 @@ internal class EntityWithNullableId public ConvertersLongId? Id { get; set; } } + internal class TestEntity2 + { + public ConvertersLongId2 Id { get; set; } + } + + internal class EntityWithNullableId2 + { + public ConvertersLongId2? Id { get; set; } + } + internal class TypeWithDictionaryKeys { public Dictionary Values { get; set; } From 697a30a5c419932b47b68331709a630714824e67 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 10 Nov 2023 21:28:48 +0000 Subject: [PATCH 31/47] Add string integration tests --- .../DapperTypeHandlers.cs | 1 + .../Enums.cs | 3 + .../StringIdTests.cs | 300 ++++++++++++++---- 3 files changed, 235 insertions(+), 69 deletions(-) diff --git a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs index ec80cda4c..517239aea 100644 --- a/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs +++ b/test/StronglyTypedIds.IntegrationTests/DapperTypeHandlers.cs @@ -16,6 +16,7 @@ public static void AddHandlers() SqlMapper.AddTypeHandler(new ConvertersLongId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersLongId2.DapperTypeHandler()); SqlMapper.AddTypeHandler(new ConvertersStringId.DapperTypeHandler()); + SqlMapper.AddTypeHandler(new ConvertersStringId2.DapperTypeHandler()); SqlMapper.AddTypeHandler(new NullableStringId.DapperTypeHandler()); SqlMapper.AddTypeHandler(new NewIdId1.DapperTypeHandler()); } diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index 8b8a67571..5ba68235d 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -52,6 +52,9 @@ partial struct StringId { } [StronglyTypedId("string-full")] partial struct ConvertersStringId { } +[StronglyTypedId(Template.String, "string-efcore", "string-dapper", "string-newtonsoftjson")] +partial struct ConvertersStringId2 { } + [StronglyTypedId("nullablestring-full")] partial struct NullableStringId { } diff --git a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs index c27b6ff8a..9cc6e3ea0 100644 --- a/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/StringIdTests.cs @@ -38,7 +38,6 @@ public void EmptyValueIsEmpty() Assert.Equal(StringId.Empty.Value, string.Empty); } - [Fact] public void DifferentValuesAreUnequal() { @@ -72,17 +71,6 @@ public void DifferentTypesAreUnequal() Assert.NotEqual((object)bar, (object)foo); } - [Fact] - public void CanSerializeToString_WithNewtonsoftJsonProvider() - { - var foo = new ConvertersStringId("123"); - - var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); - var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); - - Assert.Equal(serializedFoo, serializedString); - } - [Fact] public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() { @@ -95,16 +83,6 @@ public void CanSerializeToNullableId_WithNewtonsoftJsonProvider() Assert.Null(deserialize.Id); } - [Fact] - public void CanSerializeToString_WithSystemTextJsonProvider() - { - var foo = new ConvertersStringId("123"); - - var serializedFoo = SystemTextJsonSerializer.Serialize(foo); - var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); - - Assert.Equal(serializedFoo, serializedString); - } #if NET6_0_OR_GREATER [Fact] public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() @@ -139,6 +117,99 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() Assert.Equal("My Value", deserialized.Values[key]); } #endif + + [Fact] + public void ImplementsInterfaces() + { + Assert.IsAssignableFrom>(StringId.Empty); + Assert.IsAssignableFrom>(StringId.Empty); + +#pragma warning disable 184 +#pragma warning disable CS0183 + Assert.True(StringId.Empty is IComparable); + Assert.True(StringId.Empty is IEquatable); +#pragma warning restore CS0183 +#pragma warning restore 184 + +#if NET6_0_OR_GREATER + Assert.IsAssignableFrom(StringId.Empty); +#endif +#if NET7_0_OR_GREATER + // doesn't compile if doesn't implement it + ParseAs("123"); + ParseSpan("123".AsSpan()); + + T ParseAs(string s) where T : IParsable + { + return T.Parse(s, null); + } + + T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + { + return T.Parse(s, null); + } +#endif + } + + [Theory] + [InlineData("")] + [InlineData("some value")] + public void TypeConverter_CanConvertToAndFrom(object value) + { + var converter = TypeDescriptor.GetConverter(typeof(StringId)); + var id = converter.ConvertFrom(value); + Assert.IsType(id); + Assert.Equal(new StringId(value?.ToString()), id); + + var reconverted = converter.ConvertTo(id, value.GetType()); + Assert.Equal(value, reconverted); + } + + [Fact] + public void CanCompareDefaults() + { + StringId original = default; + var other = StringId.Empty; + + var compare1 = original.CompareTo(other); + var compare2 = other.CompareTo(original); + Assert.Equal(compare1, -compare2); + } + + [Fact] + public void CanEquateDefaults() + { + StringId original = default; + var other = StringId.Empty; + + var equals1 = (original as IEquatable).Equals(other); + var equals2 = (other as IEquatable).Equals(original); + + Assert.Equal(equals1, equals2); + } + +#region ConvertersStringId + [Fact] + public void CanSerializeToString_WithNewtonsoftJsonProvider() + { + var foo = new ConvertersStringId("123"); + + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + Assert.Equal(serializedFoo, serializedString); + } + + [Fact] + public void CanSerializeToString_WithSystemTextJsonProvider() + { + var foo = new ConvertersStringId("123"); + + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); + + Assert.Equal(serializedFoo, serializedString); + } [Fact] public void CanDeserializeFromString_WithNewtonsoftJsonProvider() @@ -215,80 +286,137 @@ public async Task WhenDapperValueConverterUsesValueConverter() Assert.Equal(value, new ConvertersStringId("this is a value")); } - [Theory] - [InlineData("")] - [InlineData("some value")] - public void TypeConverter_CanConvertToAndFrom(object value) +#if NET6_0_OR_GREATER + [Fact] + public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() { - var converter = TypeDescriptor.GetConverter(typeof(ConvertersStringId)); - var id = converter.ConvertFrom(value); - Assert.IsType(id); - Assert.Equal(new ConvertersStringId(value?.ToString()), id); + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); - var reconverted = converter.ConvertTo(id, value.GetType()); - Assert.Equal(value, reconverted); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity { Id = Guid.NewGuid(), Name = new ConvertersStringId("some name") }; + using (var context = new ConventionsDbContext(options)) + { + context.Database.EnsureCreated(); + context.Entities.Add(original); + context.SaveChanges(); + } + + using (var context = new ConventionsDbContext(options)) + { + var all = context.Entities.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); + Assert.Equal(original.Name, retrieved.Name); + } } +#endif +#endregion +#region ConvertersStringId2 [Fact] - public void CanCompareDefaults() + public void CanSerializeToString_WithMultiTemplates_WithNewtonsoftJsonProvider() { - ConvertersStringId original = default; - var other = ConvertersStringId.Empty; + var foo = new ConvertersStringId2("123"); - var compare1 = original.CompareTo(other); - var compare2 = other.CompareTo(original); - Assert.Equal(compare1, -compare2); + var serializedFoo = NewtonsoftJsonSerializer.SerializeObject(foo); + var serializedString = NewtonsoftJsonSerializer.SerializeObject(foo.Value); + + Assert.Equal(serializedFoo, serializedString); } [Fact] - public void CanEquateDefaults() + public void CanSerializeToString_WithMultiTemplates_WithSystemTextJsonProvider() { - ConvertersStringId original = default; - var other = ConvertersStringId.Empty; + var foo = new ConvertersStringId2("123"); - var equals1 = (original as IEquatable).Equals(other); - var equals2 = (other as IEquatable).Equals(original); + var serializedFoo = SystemTextJsonSerializer.Serialize(foo); + var serializedString = SystemTextJsonSerializer.Serialize(foo.Value); - Assert.Equal(equals1, equals2); + Assert.Equal(serializedFoo, serializedString); } [Fact] - public void ImplementsInterfaces() + public void CanDeserializeFromString_WithMultiTemplates_WithNewtonsoftJsonProvider() { - Assert.IsAssignableFrom>(StringId.Empty); - Assert.IsAssignableFrom>(StringId.Empty); + var value = "123"; + var foo = new ConvertersStringId2(value); + var serializedString = NewtonsoftJsonSerializer.SerializeObject(value); -#pragma warning disable 184 -#pragma warning disable CS0183 - Assert.True(StringId.Empty is IComparable); - Assert.True(StringId.Empty is IEquatable); -#pragma warning restore CS0183 -#pragma warning restore 184 + var deserializedFoo = NewtonsoftJsonSerializer.DeserializeObject(serializedString); -#if NET6_0_OR_GREATER - Assert.IsAssignableFrom(StringId.Empty); -#endif -#if NET7_0_OR_GREATER - // doesn't compile if doesn't implement it - ParseAs("123"); - ParseSpan("123".AsSpan()); + Assert.Equal(foo, deserializedFoo); + } - T ParseAs(string s) where T : IParsable + [Fact] + public void CanDeserializeFromString_WithMultiTemplates_WithSystemTextJsonProvider() + { + var value = "123"; + var foo = new ConvertersStringId2(value); + var serializedString = SystemTextJsonSerializer.Serialize(value); + + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedString); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact] + public void WhenNoJsonConverter_WithMultiTemplates_NewtonsoftSerializesWithoutValueProperty() + { + var foo = new ConvertersStringId2("123"); + + var serialized = NewtonsoftJsonSerializer.SerializeObject(foo); + + var expected = "\"" + foo.Value + "\""; + + Assert.Equal(expected, serialized); + } + + [Fact] + public void WhenEfCoreValueConverter_WithMultiTemplates_UsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + var original = new TestEntity2 { Id = Guid.NewGuid(), Name = new ConvertersStringId2("some name") }; + using (var context = new TestDbContext(options)) { - return T.Parse(s, null); + context.Database.EnsureCreated(); + context.Entities2.Add(original); + context.SaveChanges(); } - T ParseSpan(ReadOnlySpan s) where T : ISpanParsable + using (var context = new TestDbContext(options)) { - return T.Parse(s, null); + var all = context.Entities2.ToList(); + var retrieved = Assert.Single(all); + Assert.Equal(original.Id, retrieved.Id); + Assert.Equal(original.Name, retrieved.Name); } -#endif } + [Fact] + public async Task WhenDapperValueConverter_WithMultiTemplates_UsesValueConverter() + { + using var connection = new SqliteConnection("DataSource=:memory:"); + await connection.OpenAsync(); + + var results = await connection.QueryAsync("SELECT 'this is a value'"); + + var value = Assert.Single(results); + Assert.Equal(value, new ConvertersStringId2("this is a value")); + } #if NET6_0_OR_GREATER [Fact] - public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() + public void WhenConventionBasedEfCoreValueConverter_WithMultiTemplates_UsesValueConverter() { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -297,26 +425,30 @@ public void WhenConventionBasedEfCoreValueConverterUsesValueConverter() .UseSqlite(connection) .Options; - var original = new TestEntity { Id = Guid.NewGuid(), Name = new ConvertersStringId("some name") }; + var original = new TestEntity2 { Id = Guid.NewGuid(), Name = new ConvertersStringId2("some name") }; using (var context = new ConventionsDbContext(options)) { context.Database.EnsureCreated(); - context.Entities.Add(original); + context.Entities2.Add(original); context.SaveChanges(); } using (var context = new ConventionsDbContext(options)) { - var all = context.Entities.ToList(); + var all = context.Entities2.ToList(); var retrieved = Assert.Single(all); Assert.Equal(original.Id, retrieved.Id); Assert.Equal(original.Name, retrieved.Name); } } +#endif +#endregion +#if NET6_0_OR_GREATER internal class ConventionsDbContext : DbContext { public DbSet Entities { get; set; } + public DbSet Entities2 { get; set; } public ConventionsDbContext(DbContextOptions options) : base(options) { @@ -327,6 +459,9 @@ protected override void ConfigureConventions(ModelConfigurationBuilder configura configurationBuilder .Properties() .HaveConversion(); + configurationBuilder + .Properties() + .HaveConversion(); } protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -338,6 +473,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Property(x => x.Id) .ValueGeneratedNever(); }); + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Id) + .ValueGeneratedNever(); + }); } } #endif @@ -345,6 +487,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) internal class TestDbContext : DbContext { public DbSet Entities { get; set; } + public DbSet Entities2 { get; set; } public TestDbContext(DbContextOptions options) : base(options) { @@ -360,6 +503,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasConversion(new ConvertersStringId.EfCoreValueConverter()) .ValueGeneratedNever(); }); + modelBuilder + .Entity(builder => + { + builder + .Property(x => x.Name) + .HasConversion(new ConvertersStringId2.EfCoreValueConverter()) + .ValueGeneratedNever(); + }); } } @@ -374,6 +525,17 @@ internal class EntityWithNullableId public ConvertersStringId? Id { get; set; } } + internal class TestEntity2 + { + public Guid Id { get; set; } + public ConvertersStringId2 Name { get; set; } + } + + internal class EntityWithNullableId2 + { + public ConvertersStringId2? Id { get; set; } + } + internal class TypeWithDictionaryKeys { public Dictionary Values { get; set; } From 3503c9989a02eb12593e4e35fae49e44234c92fb Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 10 Nov 2023 21:28:58 +0000 Subject: [PATCH 32/47] Fix typos --- .../{int-newstonsoftjson.typedid => int-newtonsoftjson.typedid} | 0 .../{long-newtnosoftjson.typedid => long-newtonsoftjson.typedid} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/StronglyTypedIds.Templates/{int-newstonsoftjson.typedid => int-newtonsoftjson.typedid} (100%) rename src/StronglyTypedIds.Templates/{long-newtnosoftjson.typedid => long-newtonsoftjson.typedid} (100%) diff --git a/src/StronglyTypedIds.Templates/int-newstonsoftjson.typedid b/src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid similarity index 100% rename from src/StronglyTypedIds.Templates/int-newstonsoftjson.typedid rename to src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid diff --git a/src/StronglyTypedIds.Templates/long-newtnosoftjson.typedid b/src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid similarity index 100% rename from src/StronglyTypedIds.Templates/long-newtnosoftjson.typedid rename to src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid From f1dadf0c9a5e7b1398c14aabd5b14e09628d4577 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 18:05:23 +0000 Subject: [PATCH 33/47] Update diagnostics to ensure unique (breaking change) --- .../Diagnostics/InvalidTemplateNameDiagnostic.cs | 2 +- .../Diagnostics/MultipleAssemblyAttributeDiagnostic.cs | 2 +- src/StronglyTypedIds/Diagnostics/NotPartialDiagnostic.cs | 2 +- src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs index be8b4700b..0cf8f4137 100644 --- a/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/InvalidTemplateNameDiagnostic.cs @@ -4,7 +4,7 @@ namespace StronglyTypedIds.Diagnostics; internal static class InvalidTemplateNameDiagnostic { - internal const string Id = "STI8"; + internal const string Id = "STRONGID001"; internal const string Message = "The template name must not be null or whitespace."; internal const string Title = "Invalid template name"; diff --git a/src/StronglyTypedIds/Diagnostics/MultipleAssemblyAttributeDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/MultipleAssemblyAttributeDiagnostic.cs index dfadb4f1c..98ecc2126 100644 --- a/src/StronglyTypedIds/Diagnostics/MultipleAssemblyAttributeDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/MultipleAssemblyAttributeDiagnostic.cs @@ -4,7 +4,7 @@ namespace StronglyTypedIds.Diagnostics; internal static class MultipleAssemblyAttributeDiagnostic { - internal const string Id = "STI6"; + internal const string Id = "STRONGID004"; internal const string Message = "You may only have one instance of the StronglyTypedIdDefaults assembly attribute"; internal const string Title = "Multiple assembly attributes"; diff --git a/src/StronglyTypedIds/Diagnostics/NotPartialDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/NotPartialDiagnostic.cs index c1a66d922..dd50465be 100644 --- a/src/StronglyTypedIds/Diagnostics/NotPartialDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/NotPartialDiagnostic.cs @@ -4,7 +4,7 @@ namespace StronglyTypedIds.Diagnostics { internal static class NotPartialDiagnostic { - internal const string Id = "STI2"; + internal const string Id = "STRONGID003"; internal const string Message = "The target of the StronglyTypedId attribute must be declared as partial."; internal const string Title = "Must be partial"; diff --git a/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs b/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs index d836e37c5..7347efd9d 100644 --- a/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs +++ b/src/StronglyTypedIds/Diagnostics/UnknownTemplateDiagnostic.cs @@ -4,7 +4,7 @@ namespace StronglyTypedIds.Diagnostics; internal static class UnknownTemplateDiagnostic { - internal const string Id = "STI7"; + internal const string Id = "STRONGID002"; internal const string Title = "Unknown .typedid template"; internal const string TemplateName = nameof(TemplateName); From 1d86b74c5b6ed0048c79bba7b3f528b45b0c17e0 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 18:11:19 +0000 Subject: [PATCH 34/47] Remove unused includes --- .../StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj | 1 - .../StronglyTypedIds.Nuget.IntegrationTests.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj b/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj index 7e9d04e7c..c8c04769c 100644 --- a/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj +++ b/test/StronglyTypedIds.Nuget.Attributes.IntegrationTests/StronglyTypedIds.Nuget.Attributes.IntegrationTests.csproj @@ -9,7 +9,6 @@ - diff --git a/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj b/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj index e4749e998..06ad863b3 100644 --- a/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj +++ b/test/StronglyTypedIds.Nuget.IntegrationTests/StronglyTypedIds.Nuget.IntegrationTests.csproj @@ -8,7 +8,6 @@ - From a61bd2ad489f67dbd8bfc28adc9a08a7ff92f27d Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 18:40:27 +0000 Subject: [PATCH 35/47] Fix templates package --- .../StronglyTypedIds.Templates.csproj | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj b/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj index 6571d9600..a720ced3a 100644 --- a/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj +++ b/src/StronglyTypedIds.Templates/StronglyTypedIds.Templates.csproj @@ -9,17 +9,9 @@ latest - - - - - - - - - + \ No newline at end of file From df298bc71a89631195de9fc64f873df6146281e0 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 18:44:23 +0000 Subject: [PATCH 36/47] Show the additional templates in the project --- .../StronglyTypedId.Templates.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StronglyTypedIds.Templates/StronglyTypedId.Templates.targets b/src/StronglyTypedIds.Templates/StronglyTypedId.Templates.targets index 9df47b89b..b7db8fde5 100644 --- a/src/StronglyTypedIds.Templates/StronglyTypedId.Templates.targets +++ b/src/StronglyTypedIds.Templates/StronglyTypedId.Templates.targets @@ -2,7 +2,7 @@ - false + true From 1cf3f57be61ef0112eb8cd2f988969b9be4d739c Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 18:49:23 +0000 Subject: [PATCH 37/47] Add 8.0.x to Github actions --- .github/workflows/BuildAndPack.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/BuildAndPack.yml b/.github/workflows/BuildAndPack.yml index cdd141ece..60e5a5e3e 100644 --- a/.github/workflows/BuildAndPack.yml +++ b/.github/workflows/BuildAndPack.yml @@ -36,6 +36,7 @@ jobs: - uses: actions/setup-dotnet@v3 with: dotnet-version: | + 8.0.x 7.0.x 6.0.x 5.0.x @@ -66,6 +67,7 @@ jobs: - uses: actions/setup-dotnet@v3 with: dotnet-version: | + 8.0.x 7.0.x 6.0.x 5.0.x @@ -96,6 +98,7 @@ jobs: - uses: actions/setup-dotnet@v3 with: dotnet-version: | + 8.0.x 7.0.x 6.0.x 5.0.x From d27e3e64367d365d9c59323685a8a6246be4b746 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 19:05:30 +0000 Subject: [PATCH 38/47] Tweak codefix action --- .../Diagnostics/UnknownTemplateCodeFixProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StronglyTypedIds/Diagnostics/UnknownTemplateCodeFixProvider.cs b/src/StronglyTypedIds/Diagnostics/UnknownTemplateCodeFixProvider.cs index fa42a632a..282571b30 100644 --- a/src/StronglyTypedIds/Diagnostics/UnknownTemplateCodeFixProvider.cs +++ b/src/StronglyTypedIds/Diagnostics/UnknownTemplateCodeFixProvider.cs @@ -77,7 +77,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix( CodeAction.Create( - $"Add {templateName}.typedid template to the project", + $"Add '{templateName}.typedid' template to the project", cancellationToken => GetTransformedSolutionAsync(context.Document, templateName, cancellationToken), nameof(UnknownTemplateCodeFixProvider)), diagnostic); From 64798d33215647705785a146a13b876bfd98d82f Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 19:43:27 +0000 Subject: [PATCH 39/47] Fix windows-specific paths --- test/StronglyTypedIds.Tests/TestHelpers.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/StronglyTypedIds.Tests/TestHelpers.cs b/test/StronglyTypedIds.Tests/TestHelpers.cs index 791ec5fce..f7e1e3894 100644 --- a/test/StronglyTypedIds.Tests/TestHelpers.cs +++ b/test/StronglyTypedIds.Tests/TestHelpers.cs @@ -17,7 +17,6 @@ internal static class TestHelpers public static (ImmutableArray Diagnostics, string Output) GetGeneratedOutput(string source, bool includeAttributes = true) where T : IIncrementalGenerator, new() { - var attr = new StronglyTypedIdAttribute(); var syntaxTree = CSharpSyntaxTree.ParseText(source); var references = AppDomain.CurrentDomain.GetAssemblies() .Where(_ => !_.IsDynamic && !string.IsNullOrWhiteSpace(_.Location)) @@ -54,7 +53,7 @@ private static ImmutableArray LoadEmbeddedResourcesAsAdditionalT texts.AddRange(assembly.GetManifestResourceNames() .Select(name => new TestAdditionalText( text: LoadEmbeddedResource(assembly, name), - path: $"C:\\test\\Templates\\{Path.GetExtension(Path.GetFileNameWithoutExtension(name)).Substring(1)}.typedid"))); + path: Path.Combine("c:", "test", "Templates", Path.GetExtension(Path.GetFileNameWithoutExtension(name)).Substring(1) + ".typedid")))); return texts.ToImmutable(); } From 65d570787bd49f34288d06451c4e3ed829528fc2 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 20:14:32 +0000 Subject: [PATCH 40/47] Ensure we test both in-project IDs and "external" IDs --- StronglyTypedId.sln | 30 ++++++++ ...pedIds.IntegrationTests.ExternalIds.csproj | 25 +++++++ .../xunit.runner.json | 4 + .../Enums.cs | 74 +++++++++++++++++++ ...nglyTypedIds.IntegrationTests.Types.csproj | 22 ++++++ .../Enums.cs | 44 +++++------ 6 files changed, 177 insertions(+), 22 deletions(-) create mode 100644 test/StronglyTypedIds.IntegrationTests.ExternalIds/StronglyTypedIds.IntegrationTests.ExternalIds.csproj create mode 100644 test/StronglyTypedIds.IntegrationTests.ExternalIds/xunit.runner.json create mode 100644 test/StronglyTypedIds.IntegrationTests.Types/Enums.cs create mode 100644 test/StronglyTypedIds.IntegrationTests.Types/StronglyTypedIds.IntegrationTests.Types.csproj diff --git a/StronglyTypedId.sln b/StronglyTypedId.sln index 036d076bd..4620315b7 100644 --- a/StronglyTypedId.sln +++ b/StronglyTypedId.sln @@ -34,6 +34,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Nuget.Attr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.Templates", "src\StronglyTypedIds.Templates\StronglyTypedIds.Templates.csproj", "{336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.IntegrationTests.Types", "test\StronglyTypedIds.IntegrationTests.Types\StronglyTypedIds.IntegrationTests.Types.csproj", "{A5804404-E5A5-4F05-86E2-B2A11D370498}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StronglyTypedIds.IntegrationTests.ExternalIds", "test\StronglyTypedIds.IntegrationTests.ExternalIds\StronglyTypedIds.IntegrationTests.ExternalIds.csproj", "{07875BB0-EFEE-4F90-AAB8-4B11F78C8047}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -118,6 +122,30 @@ Global {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Release|x64.Build.0 = Release|Any CPU {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Release|x86.ActiveCfg = Release|Any CPU {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C}.Release|x86.Build.0 = Release|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Debug|x64.ActiveCfg = Debug|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Debug|x64.Build.0 = Debug|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Debug|x86.ActiveCfg = Debug|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Debug|x86.Build.0 = Debug|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Release|Any CPU.Build.0 = Release|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Release|x64.ActiveCfg = Release|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Release|x64.Build.0 = Release|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Release|x86.ActiveCfg = Release|Any CPU + {A5804404-E5A5-4F05-86E2-B2A11D370498}.Release|x86.Build.0 = Release|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Debug|x64.ActiveCfg = Debug|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Debug|x64.Build.0 = Debug|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Debug|x86.ActiveCfg = Debug|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Debug|x86.Build.0 = Debug|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Release|Any CPU.Build.0 = Release|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Release|x64.ActiveCfg = Release|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Release|x64.Build.0 = Release|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Release|x86.ActiveCfg = Release|Any CPU + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -130,6 +158,8 @@ Global {A7355210-7DDC-4968-84B7-79002113EA6E} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} {19A9B323-8C0B-4D1B-A20C-8CECFFD37F23} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} {336D7EE4-90BA-4BFC-99F6-D70B8D494E8C} = {EE1258BD-3422-4F55-B9CF-B4D6C95DAD68} + {A5804404-E5A5-4F05-86E2-B2A11D370498} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} + {07875BB0-EFEE-4F90-AAB8-4B11F78C8047} = {D1907D86-8FFC-4178-A3DB-0ADBDD282C64} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8D1F0534-B8AD-4CFA-9C14-CBC757BCB1E1} diff --git a/test/StronglyTypedIds.IntegrationTests.ExternalIds/StronglyTypedIds.IntegrationTests.ExternalIds.csproj b/test/StronglyTypedIds.IntegrationTests.ExternalIds/StronglyTypedIds.IntegrationTests.ExternalIds.csproj new file mode 100644 index 000000000..833c1281f --- /dev/null +++ b/test/StronglyTypedIds.IntegrationTests.ExternalIds/StronglyTypedIds.IntegrationTests.ExternalIds.csproj @@ -0,0 +1,25 @@ + + + + netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 + net48;$(TargetFrameworks) + false + true + + + + + + + + + + + + + + + + + + diff --git a/test/StronglyTypedIds.IntegrationTests.ExternalIds/xunit.runner.json b/test/StronglyTypedIds.IntegrationTests.ExternalIds/xunit.runner.json new file mode 100644 index 000000000..533ef25c1 --- /dev/null +++ b/test/StronglyTypedIds.IntegrationTests.ExternalIds/xunit.runner.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", + "shadowCopy": false +} \ No newline at end of file diff --git a/test/StronglyTypedIds.IntegrationTests.Types/Enums.cs b/test/StronglyTypedIds.IntegrationTests.Types/Enums.cs new file mode 100644 index 000000000..033a09cce --- /dev/null +++ b/test/StronglyTypedIds.IntegrationTests.Types/Enums.cs @@ -0,0 +1,74 @@ +#nullable enable +using System; + +namespace StronglyTypedIds.IntegrationTests.Types; + + +[StronglyTypedId] +public partial struct DefaultId1 { } + +[StronglyTypedId] +public partial struct DefaultId2 { } + +[StronglyTypedId(Template.Guid)] +public partial struct GuidId1 { } + +[StronglyTypedId("guid-full")] +public partial struct ConvertersGuidId { } + +[StronglyTypedId(Template.Guid, "guid-efcore", "guid-dapper", "guid-newtonsoftjson")] +public partial struct ConvertersGuidId2 { } + +[StronglyTypedId(Template.Guid)] +public partial struct GuidId2 { } + +[StronglyTypedId(Template.Int)] +public partial struct IntId { } + +[StronglyTypedId("int-full")] +public partial struct ConvertersIntId { } + +[StronglyTypedId(Template.Int, "int-efcore", "int-dapper", "int-newtonsoftjson")] +public partial struct ConvertersIntId2 { } + +[StronglyTypedId(Template.Long)] +public partial struct LongId { } + +[StronglyTypedId("long-full")] +public partial struct ConvertersLongId { } + +[StronglyTypedId(Template.Long, "long-efcore", "long-dapper", "long-newtonsoftjson")] +public partial struct ConvertersLongId2 { } + +[StronglyTypedId("newid-full")] +public partial struct NewIdId1 { } + +[StronglyTypedId("newid-full")] +public partial struct NewIdId2 { } + +[StronglyTypedId(Template.String)] +public partial struct StringId { } + +[StronglyTypedId("string-full")] +public partial struct ConvertersStringId { } + +[StronglyTypedId(Template.String, "string-efcore", "string-dapper", "string-newtonsoftjson")] +public partial struct ConvertersStringId2 { } + +[StronglyTypedId("nullablestring-full")] +public partial struct NullableStringId { } + +public partial class SomeType where T : new() +{ + public partial record struct NestedType + { + public partial struct MoreNesting + { + [StronglyTypedId] + public readonly partial struct VeryNestedId + { + } + } + } +} + diff --git a/test/StronglyTypedIds.IntegrationTests.Types/StronglyTypedIds.IntegrationTests.Types.csproj b/test/StronglyTypedIds.IntegrationTests.Types/StronglyTypedIds.IntegrationTests.Types.csproj new file mode 100644 index 000000000..e07b7f3de --- /dev/null +++ b/test/StronglyTypedIds.IntegrationTests.Types/StronglyTypedIds.IntegrationTests.Types.csproj @@ -0,0 +1,22 @@ + + + + netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 + net48;$(TargetFrameworks) + false + true + false + + + + + + + + + + + + + + diff --git a/test/StronglyTypedIds.IntegrationTests/Enums.cs b/test/StronglyTypedIds.IntegrationTests/Enums.cs index 5ba68235d..66e88e574 100644 --- a/test/StronglyTypedIds.IntegrationTests/Enums.cs +++ b/test/StronglyTypedIds.IntegrationTests/Enums.cs @@ -5,67 +5,67 @@ namespace StronglyTypedIds.IntegrationTests.Types; [StronglyTypedId] -partial struct DefaultId1 { } +internal partial struct DefaultId1 { } [StronglyTypedId] -public partial struct DefaultId2 { } +internal partial struct DefaultId2 { } [StronglyTypedId(Template.Guid)] -partial struct GuidId1 { } +internal partial struct GuidId1 { } [StronglyTypedId("guid-full")] -partial struct ConvertersGuidId { } +internal partial struct ConvertersGuidId { } [StronglyTypedId(Template.Guid, "guid-efcore", "guid-dapper", "guid-newtonsoftjson")] -partial struct ConvertersGuidId2 { } +internal partial struct ConvertersGuidId2 { } [StronglyTypedId(Template.Guid)] -public partial struct GuidId2 { } +internal partial struct GuidId2 { } [StronglyTypedId(Template.Int)] -partial struct IntId { } +internal partial struct IntId { } [StronglyTypedId("int-full")] -partial struct ConvertersIntId { } +internal partial struct ConvertersIntId { } [StronglyTypedId(Template.Int, "int-efcore", "int-dapper", "int-newtonsoftjson")] -partial struct ConvertersIntId2 { } +internal partial struct ConvertersIntId2 { } [StronglyTypedId(Template.Long)] -partial struct LongId { } +internal partial struct LongId { } [StronglyTypedId("long-full")] -partial struct ConvertersLongId { } +internal partial struct ConvertersLongId { } [StronglyTypedId(Template.Long, "long-efcore", "long-dapper", "long-newtonsoftjson")] -partial struct ConvertersLongId2 { } +internal partial struct ConvertersLongId2 { } [StronglyTypedId("newid-full")] -partial struct NewIdId1 { } +internal partial struct NewIdId1 { } [StronglyTypedId("newid-full")] -partial struct NewIdId2 { } +internal partial struct NewIdId2 { } [StronglyTypedId(Template.String)] -partial struct StringId { } +internal partial struct StringId { } [StronglyTypedId("string-full")] -partial struct ConvertersStringId { } +internal partial struct ConvertersStringId { } [StronglyTypedId(Template.String, "string-efcore", "string-dapper", "string-newtonsoftjson")] -partial struct ConvertersStringId2 { } +internal partial struct ConvertersStringId2 { } [StronglyTypedId("nullablestring-full")] -partial struct NullableStringId { } +internal partial struct NullableStringId { } -public partial class SomeType where T : new() +internal partial class SomeType where T : new() { - public partial record struct NestedType + internal partial record struct NestedType { - public partial struct MoreNesting + internal partial struct MoreNesting { [StronglyTypedId] - public readonly partial struct VeryNestedId + internal readonly partial struct VeryNestedId { } } From 5c09ea435071be105d285191f829b0819c035ce1 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 20:32:28 +0000 Subject: [PATCH 41/47] Make all the converts public by default It doesn't really make sense that their not... --- src/StronglyTypedIds.Templates/guid-full.typedid | 6 +++--- .../guid-newtonsoftjson.typedid | 2 +- src/StronglyTypedIds.Templates/int-full.typedid | 6 +++--- src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid | 2 +- src/StronglyTypedIds.Templates/long-full.typedid | 6 +++--- .../long-newtonsoftjson.typedid | 2 +- src/StronglyTypedIds.Templates/newid-full.typedid | 6 +++--- .../nullablestring-full.typedid | 6 +++--- src/StronglyTypedIds.Templates/string-full.typedid | 6 +++--- .../string-newtonsoftjson.typedid | 2 +- src/StronglyTypedIds/EmbeddedSources.Guid.cs | 4 ++-- src/StronglyTypedIds/EmbeddedSources.Int.cs | 4 ++-- src/StronglyTypedIds/EmbeddedSources.Long.cs | 4 ++-- src/StronglyTypedIds/EmbeddedSources.String.cs | 4 ++-- ...sts.CanGenerateDefaultIdInGlobalNamespace.verified.txt | 4 ++-- ...neratorTests.CanGenerateForCustomTemplate.verified.txt | 6 +++--- ...teGenericVeryNestedIdInFileScopeNamespace.verified.txt | 4 ++-- ...rTests.CanGenerateIdInFileScopedNamespace.verified.txt | 4 ++-- ...IdGeneratorTests.CanGenerateIdInNamespace.verified.txt | 4 ++-- ...rTests.CanGenerateMultipleIdsWithSameName.verified.txt | 8 ++++---- ...s.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt | 4 ++-- ...s.CanGenerateNestedIdInFileScopeNamespace.verified.txt | 4 ++-- ...rTests.CanGenerateNonDefaultIdInNamespace.verified.txt | 4 ++-- ...nGenerateVeryNestedIdInFileScopeNamespace.verified.txt | 4 ++-- ...ltsWithCustomTemplateUsingGlobalAttribute.verified.txt | 6 +++--- ...eDefaultsWithTemplateUsingGlobalAttribute.verified.txt | 4 ++-- ...oviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt | 6 +++--- ...roviderUnitTests.UsesBuiltInTemplates_Int.verified.txt | 6 +++--- ...oviderUnitTests.UsesBuiltInTemplates_Long.verified.txt | 6 +++--- ...iderUnitTests.UsesBuiltInTemplates_String.verified.txt | 6 +++--- 30 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/StronglyTypedIds.Templates/guid-full.typedid b/src/StronglyTypedIds.Templates/guid-full.typedid index 61fe33264..039167830 100644 --- a/src/StronglyTypedIds.Templates/guid-full.typedid +++ b/src/StronglyTypedIds.Templates/guid-full.typedid @@ -38,7 +38,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -79,7 +79,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -229,7 +229,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid index 5fe6395c2..6bea0ae14 100644 --- a/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid +++ b/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid @@ -1,7 +1,7 @@ [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID { - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/int-full.typedid b/src/StronglyTypedIds.Templates/int-full.typedid index b2208465b..6db8e0a09 100644 --- a/src/StronglyTypedIds.Templates/int-full.typedid +++ b/src/StronglyTypedIds.Templates/int-full.typedid @@ -37,7 +37,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -78,7 +78,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -225,7 +225,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid index 6d492433a..1a22ebefe 100644 --- a/src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid +++ b/src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid @@ -1,7 +1,7 @@ [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID { - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/long-full.typedid b/src/StronglyTypedIds.Templates/long-full.typedid index 78447edfe..475870809 100644 --- a/src/StronglyTypedIds.Templates/long-full.typedid +++ b/src/StronglyTypedIds.Templates/long-full.typedid @@ -37,7 +37,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -78,7 +78,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(long) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -226,7 +226,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid index 5ae2a6394..9db84a73a 100644 --- a/src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid +++ b/src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid @@ -1,7 +1,7 @@ [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID { - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/newid-full.typedid b/src/StronglyTypedIds.Templates/newid-full.typedid index 779baef92..24b83177a 100644 --- a/src/StronglyTypedIds.Templates/newid-full.typedid +++ b/src/StronglyTypedIds.Templates/newid-full.typedid @@ -38,7 +38,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -87,7 +87,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || typeToConvert == typeof(global::System.Guid) || base.CanConvert(typeToConvert); @@ -232,7 +232,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/nullablestring-full.typedid b/src/StronglyTypedIds.Templates/nullablestring-full.typedid index 2c86980fa..b5de065e2 100644 --- a/src/StronglyTypedIds.Templates/nullablestring-full.typedid +++ b/src/StronglyTypedIds.Templates/nullablestring-full.typedid @@ -52,7 +52,7 @@ (_, _) => Value.CompareTo(other.Value), }; - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -86,7 +86,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -215,7 +215,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/string-full.typedid b/src/StronglyTypedIds.Templates/string-full.typedid index bdb3b9195..b1cceed26 100644 --- a/src/StronglyTypedIds.Templates/string-full.typedid +++ b/src/StronglyTypedIds.Templates/string-full.typedid @@ -52,7 +52,7 @@ (_, _) => Value.CompareTo(other.Value), }; - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -88,7 +88,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -212,7 +212,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid index bc09e3840..95bf00b8f 100644 --- a/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid +++ b/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid @@ -1,7 +1,7 @@ [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID { - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds/EmbeddedSources.Guid.cs b/src/StronglyTypedIds/EmbeddedSources.Guid.cs index 51fcd9b2c..c64f85d0e 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Guid.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Guid.cs @@ -40,7 +40,7 @@ public override bool Equals(object? obj) /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -81,7 +81,7 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/src/StronglyTypedIds/EmbeddedSources.Int.cs b/src/StronglyTypedIds/EmbeddedSources.Int.cs index 59773ca62..e731b68a4 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Int.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Int.cs @@ -39,7 +39,7 @@ public override bool Equals(object? obj) /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -80,7 +80,7 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/src/StronglyTypedIds/EmbeddedSources.Long.cs b/src/StronglyTypedIds/EmbeddedSources.Long.cs index 83775e092..a825f35a8 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Long.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Long.cs @@ -39,7 +39,7 @@ public override bool Equals(object? obj) /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -80,7 +80,7 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(long) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/src/StronglyTypedIds/EmbeddedSources.String.cs b/src/StronglyTypedIds/EmbeddedSources.String.cs index b83bcd2b1..1a2175283 100644 --- a/src/StronglyTypedIds/EmbeddedSources.String.cs +++ b/src/StronglyTypedIds/EmbeddedSources.String.cs @@ -54,7 +54,7 @@ public int CompareTo(PLACEHOLDERID other) (_, _) => Value.CompareTo(other.Value), }; - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -90,7 +90,7 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index 877dfdd5b..b91ea5940 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -49,7 +49,7 @@ /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -90,7 +90,7 @@ } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt index a8d5b3f3a..e3a28020b 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt @@ -52,7 +52,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -101,7 +101,7 @@ namespace SomeNamespace } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || typeToConvert == typeof(global::System.Guid) || base.CanConvert(typeToConvert); @@ -246,7 +246,7 @@ namespace SomeNamespace ) { } } - class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt index 1755bd1b1..6a3ac1695 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -55,7 +55,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -96,7 +96,7 @@ namespace SomeNamespace } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index 94d4c33f8..85612c116 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -51,7 +51,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ namespace SomeNamespace } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index 94d4c33f8..85612c116 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -51,7 +51,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ namespace SomeNamespace } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 73834c603..802bd3a68 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -51,7 +51,7 @@ namespace MyContracts.V1 /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ namespace MyContracts.V1 } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -268,7 +268,7 @@ namespace MyContracts.V2 /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -309,7 +309,7 @@ namespace MyContracts.V2 } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt index 66add15df..282f46562 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt @@ -108,7 +108,7 @@ /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -149,7 +149,7 @@ } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index 43447a354..0a6b497c5 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -53,7 +53,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -94,7 +94,7 @@ namespace SomeNamespace } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index 952445ebe..c77b8adbd 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -50,7 +50,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -91,7 +91,7 @@ namespace SomeNamespace } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index ea59d6ba8..1dc6c5144 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -57,7 +57,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -98,7 +98,7 @@ namespace SomeNamespace } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt index 02eb53fdd..e5b53b542 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt @@ -50,7 +50,7 @@ /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -99,7 +99,7 @@ } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || typeToConvert == typeof(global::System.Guid) || base.CanConvert(typeToConvert); @@ -244,7 +244,7 @@ ) { } } - class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index 75cce0f27..43a9b443b 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -48,7 +48,7 @@ /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -89,7 +89,7 @@ } } - class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt index 9860d9b22..73c8db3cd 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt @@ -52,7 +52,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -93,7 +93,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -243,7 +243,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt index 4998abd15..0e710dde9 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt @@ -51,7 +51,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -239,7 +239,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt index be319d4a3..a2ed10aff 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt @@ -51,7 +51,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(long) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -240,7 +240,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt index a470653ea..b2cdf3a73 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt @@ -66,7 +66,7 @@ (_, _) => Value.CompareTo(other.Value), }; - class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -102,7 +102,7 @@ } } - class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -226,7 +226,7 @@ ) { } } - class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { From 33eafad9a3b0b2f20bbdf68ebfb68dc8eaf1419d Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 21:09:05 +0000 Subject: [PATCH 42/47] Add source generator tests for GuidIds --- .../GuidIdTests.cs | 50 +++++++++++++++++++ .../SystemTextJsonSerializerContext.cs | 38 ++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 test/StronglyTypedIds.IntegrationTests/SystemTextJsonSerializerContext.cs diff --git a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs index e9966328c..49460b9b1 100644 --- a/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/GuidIdTests.cs @@ -141,6 +141,56 @@ public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider() Assert.True(deserialized.Values.ContainsKey(guid)); Assert.Equal("My Value", deserialized.Values[guid]); } + + [Fact] + public void CanSerializeToGuid_WithSystemTextJsonProvider_WithSourceGenerator() + { + var foo = GuidId1.New(); + + var serializedFoo = SystemTextJsonSerializer.Serialize(foo, SystemTextJsonSerializerContext.Custom.GuidId1); + var serializedGuid = SystemTextJsonSerializer.Serialize(foo.Value); + + Assert.Equal(serializedFoo, serializedGuid); + } + + [Fact] + public void CanDeserializeFromGuid_WithSystemTextJsonProvider_WithSourceGenerator() + { + var value = Guid.NewGuid(); + var foo = new GuidId1(value); + var serializedGuid = SystemTextJsonSerializer.Serialize(value); + + var deserializedFoo = SystemTextJsonSerializer.Deserialize(serializedGuid, SystemTextJsonSerializerContext.Custom.GuidId1); + + Assert.Equal(foo, deserializedFoo); + } + + [Fact(Skip = "This one doesn't seem to work, but I'm not sure if it's a source-generator limitation or a bug...")] + public void CanDeserializeDictionaryKeys_WithSystemTextJsonProvider_WithSourceGenerator() + { + var value = new TypeWithDictionaryKeys() + { + Values = new() + }; + var guid = new GuidId1(Guid.Parse("78104553-f1cd-41ec-bcb6-d3a8ff8d994d")); + value.Values.Add(guid, "My Value"); + var serialized = SystemTextJsonSerializer.Serialize(value, SystemTextJsonSerializerContext.Web.TypeWithDictionaryKeys); + + var expected = $$""" + { + "values": { + "78104553-f1cd-41ec-bcb6-d3a8ff8d994d": "My Value" + } + } + """; + Assert.Equal(serialized, expected); + + var deserialized = SystemTextJsonSerializer.Deserialize(serialized, SystemTextJsonSerializerContext.Web.TypeWithDictionaryKeys); + + Assert.NotNull(deserialized.Values); + Assert.True(deserialized.Values.ContainsKey(guid)); + Assert.Equal("My Value", deserialized.Values[guid]); + } #endif [Fact] diff --git a/test/StronglyTypedIds.IntegrationTests/SystemTextJsonSerializerContext.cs b/test/StronglyTypedIds.IntegrationTests/SystemTextJsonSerializerContext.cs new file mode 100644 index 000000000..7a388704c --- /dev/null +++ b/test/StronglyTypedIds.IntegrationTests/SystemTextJsonSerializerContext.cs @@ -0,0 +1,38 @@ +#if NET6_0_OR_GREATER +using System.Text.Json; +using System.Text.Json.Serialization; +using StronglyTypedIds.IntegrationTests.Types; + +namespace StronglyTypedIds.IntegrationTests; + +[JsonSerializable(typeof(GuidId1))] +[JsonSerializable(typeof(ConvertersGuidId))] +[JsonSerializable(typeof(ConvertersGuidId2))] +[JsonSerializable(typeof(GuidIdTests.TypeWithDictionaryKeys))] +internal partial class SystemTextJsonSerializerContext : JsonSerializerContext +{ + internal static SystemTextJsonSerializerContext Custom + => new(new JsonSerializerOptions + { + Converters = + { + new GuidId1.GuidId1SystemTextJsonConverter(), + new ConvertersGuidId.ConvertersGuidIdSystemTextJsonConverter(), + new ConvertersGuidId2.ConvertersGuidId2SystemTextJsonConverter(), + } + }); + + internal static SystemTextJsonSerializerContext Web + => new(new JsonSerializerOptions() + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + Converters = + { + new GuidId1.GuidId1SystemTextJsonConverter(), + new ConvertersGuidId.ConvertersGuidIdSystemTextJsonConverter(), + new ConvertersGuidId2.ConvertersGuidId2SystemTextJsonConverter(), + } + }); +} +#endif From 07d1db1264c2bc6c5adb0cb31cff5bdf7ea7e3f4 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sat, 11 Nov 2023 22:03:09 +0000 Subject: [PATCH 43/47] Use Ordinal Comparisons instead of culture-specific in string IDs --- src/StronglyTypedIds.Templates/nullablestring-full.typedid | 4 ++-- src/StronglyTypedIds.Templates/string-full.typedid | 4 ++-- src/StronglyTypedIds/EmbeddedSources.String.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/StronglyTypedIds.Templates/nullablestring-full.typedid b/src/StronglyTypedIds.Templates/nullablestring-full.typedid index b5de065e2..383fc9877 100644 --- a/src/StronglyTypedIds.Templates/nullablestring-full.typedid +++ b/src/StronglyTypedIds.Templates/nullablestring-full.typedid @@ -26,7 +26,7 @@ (null, null) => true, (null, _) => false, (_, null) => false, - (_, _) => Value.Equals(other.Value), + (_, _) => Value.Equals(other.Value, global::System.StringComparison.Ordinal), }; public override bool Equals(object? obj) @@ -49,7 +49,7 @@ (null, null) => 0, (null, _) => -1, (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), + (_, _) => string.CompareOrdinal(Value, other.Value), }; public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter diff --git a/src/StronglyTypedIds.Templates/string-full.typedid b/src/StronglyTypedIds.Templates/string-full.typedid index b1cceed26..14ec8101c 100644 --- a/src/StronglyTypedIds.Templates/string-full.typedid +++ b/src/StronglyTypedIds.Templates/string-full.typedid @@ -26,7 +26,7 @@ (null, null) => true, (null, _) => false, (_, null) => false, - (_, _) => Value.Equals(other.Value), + (_, _) => Value.Equals(other.Value, global::System.StringComparison.Ordinal), }; public override bool Equals(object? obj) @@ -49,7 +49,7 @@ (null, null) => 0, (null, _) => -1, (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), + (_, _) => string.CompareOrdinal(Value, other.Value), }; public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter diff --git a/src/StronglyTypedIds/EmbeddedSources.String.cs b/src/StronglyTypedIds/EmbeddedSources.String.cs index 1a2175283..6d0218631 100644 --- a/src/StronglyTypedIds/EmbeddedSources.String.cs +++ b/src/StronglyTypedIds/EmbeddedSources.String.cs @@ -28,7 +28,7 @@ public bool Equals(PLACEHOLDERID other) (null, null) => true, (null, _) => false, (_, null) => false, - (_, _) => Value.Equals(other.Value), + (_, _) => Value.Equals(other.Value, global::System.StringComparison.Ordinal), }; public override bool Equals(object? obj) @@ -51,7 +51,7 @@ public int CompareTo(PLACEHOLDERID other) (null, null) => 0, (null, _) => -1, (_, null) => 1, - (_, _) => Value.CompareTo(other.Value), + (_, _) => string.CompareOrdinal(Value, other.Value), }; public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter From aeab4b7d6381a12738953d218c28eff5b4e5b241 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sun, 12 Nov 2023 11:51:21 +0000 Subject: [PATCH 44/47] Add test for the nullable --- .../NullableStringIdTests.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs index 6264bbcb8..35ab555c3 100644 --- a/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs +++ b/test/StronglyTypedIds.IntegrationTests/NullableStringIdTests.cs @@ -16,6 +16,14 @@ namespace StronglyTypedIds.IntegrationTests { public class NullableStringIdTests { + [Fact] + public void CanUseNull() + { + var foo1 = new NullableStringId(null); + + Assert.Null(foo1.Value); + } + [Fact] public void SameValuesAreEqual() { From b9d3a25c2744a867a2914717a18dc13ffb0086d2 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sun, 12 Nov 2023 11:58:04 +0000 Subject: [PATCH 45/47] Make all converters partial --- src/StronglyTypedIds.Templates/guid-dapper.typedid | 2 +- src/StronglyTypedIds.Templates/guid-efcore.typedid | 2 +- src/StronglyTypedIds.Templates/guid-full.typedid | 10 +++++----- .../guid-newtonsoftjson.typedid | 2 +- src/StronglyTypedIds.Templates/int-dapper.typedid | 2 +- src/StronglyTypedIds.Templates/int-efcore.typedid | 2 +- src/StronglyTypedIds.Templates/int-full.typedid | 10 +++++----- .../int-newtonsoftjson.typedid | 2 +- src/StronglyTypedIds.Templates/long-dapper.typedid | 2 +- src/StronglyTypedIds.Templates/long-efcore.typedid | 2 +- src/StronglyTypedIds.Templates/long-full.typedid | 10 +++++----- .../long-newtonsoftjson.typedid | 2 +- src/StronglyTypedIds.Templates/newid-full.typedid | 10 +++++----- .../nullablestring-full.typedid | 10 +++++----- src/StronglyTypedIds.Templates/string-dapper.typedid | 2 +- src/StronglyTypedIds.Templates/string-efcore.typedid | 2 +- src/StronglyTypedIds.Templates/string-full.typedid | 10 +++++----- .../string-newtonsoftjson.typedid | 2 +- src/StronglyTypedIds/EmbeddedSources.Guid.cs | 4 ++-- src/StronglyTypedIds/EmbeddedSources.Int.cs | 4 ++-- src/StronglyTypedIds/EmbeddedSources.Long.cs | 4 ++-- src/StronglyTypedIds/EmbeddedSources.String.cs | 4 ++-- ....CanGenerateDefaultIdInGlobalNamespace.verified.txt | 4 ++-- ...atorTests.CanGenerateForCustomTemplate.verified.txt | 10 +++++----- ...enericVeryNestedIdInFileScopeNamespace.verified.txt | 4 ++-- ...sts.CanGenerateIdInFileScopedNamespace.verified.txt | 4 ++-- ...eneratorTests.CanGenerateIdInNamespace.verified.txt | 4 ++-- ...sts.CanGenerateMultipleIdsWithSameName.verified.txt | 8 ++++---- ...anGenerateMultipleTemplatesWithBuiltIn.verified.txt | 8 ++++---- ...enerateMultipleTemplatesWithoutBuiltIn.verified.txt | 4 ++-- ...anGenerateNestedIdInFileScopeNamespace.verified.txt | 4 ++-- ...sts.CanGenerateNonDefaultIdInNamespace.verified.txt | 4 ++-- ...nerateVeryNestedIdInFileScopeNamespace.verified.txt | 4 ++-- ...WithCustomTemplateUsingGlobalAttribute.verified.txt | 10 +++++----- ...faultsWithTemplateUsingGlobalAttribute.verified.txt | 4 ++-- ...derUnitTests.UsesBuiltInTemplates_Guid.verified.txt | 10 +++++----- ...iderUnitTests.UsesBuiltInTemplates_Int.verified.txt | 10 +++++----- ...derUnitTests.UsesBuiltInTemplates_Long.verified.txt | 10 +++++----- ...rUnitTests.UsesBuiltInTemplates_String.verified.txt | 10 +++++----- 39 files changed, 106 insertions(+), 106 deletions(-) diff --git a/src/StronglyTypedIds.Templates/guid-dapper.typedid b/src/StronglyTypedIds.Templates/guid-dapper.typedid index 0d8be2d10..2453e2c83 100644 --- a/src/StronglyTypedIds.Templates/guid-dapper.typedid +++ b/src/StronglyTypedIds.Templates/guid-dapper.typedid @@ -1,6 +1,6 @@ partial struct PLACEHOLDERID { - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { diff --git a/src/StronglyTypedIds.Templates/guid-efcore.typedid b/src/StronglyTypedIds.Templates/guid-efcore.typedid index 4c8af273f..f6a59d0a5 100644 --- a/src/StronglyTypedIds.Templates/guid-efcore.typedid +++ b/src/StronglyTypedIds.Templates/guid-efcore.typedid @@ -1,6 +1,6 @@ partial struct PLACEHOLDERID { - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) diff --git a/src/StronglyTypedIds.Templates/guid-full.typedid b/src/StronglyTypedIds.Templates/guid-full.typedid index 039167830..a0fa78b5f 100644 --- a/src/StronglyTypedIds.Templates/guid-full.typedid +++ b/src/StronglyTypedIds.Templates/guid-full.typedid @@ -38,7 +38,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -79,7 +79,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -200,7 +200,7 @@ => Value.TryFormat(destination, out charsWritten, format); #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -218,7 +218,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -229,7 +229,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid index 6bea0ae14..8fae4b82a 100644 --- a/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid +++ b/src/StronglyTypedIds.Templates/guid-newtonsoftjson.typedid @@ -1,7 +1,7 @@ [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID { - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/int-dapper.typedid b/src/StronglyTypedIds.Templates/int-dapper.typedid index a7e53efc0..277a4e1f1 100644 --- a/src/StronglyTypedIds.Templates/int-dapper.typedid +++ b/src/StronglyTypedIds.Templates/int-dapper.typedid @@ -1,6 +1,6 @@ partial struct PLACEHOLDERID { - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { diff --git a/src/StronglyTypedIds.Templates/int-efcore.typedid b/src/StronglyTypedIds.Templates/int-efcore.typedid index 83f25403b..c1f8fb3c6 100644 --- a/src/StronglyTypedIds.Templates/int-efcore.typedid +++ b/src/StronglyTypedIds.Templates/int-efcore.typedid @@ -1,6 +1,6 @@ partial struct PLACEHOLDERID { - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) diff --git a/src/StronglyTypedIds.Templates/int-full.typedid b/src/StronglyTypedIds.Templates/int-full.typedid index 6db8e0a09..520108330 100644 --- a/src/StronglyTypedIds.Templates/int-full.typedid +++ b/src/StronglyTypedIds.Templates/int-full.typedid @@ -37,7 +37,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -78,7 +78,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -195,7 +195,7 @@ => Value.TryFormat(destination, out charsWritten, format); #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -214,7 +214,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -225,7 +225,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid index 1a22ebefe..22de7b015 100644 --- a/src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid +++ b/src/StronglyTypedIds.Templates/int-newtonsoftjson.typedid @@ -1,7 +1,7 @@ [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID { - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/long-dapper.typedid b/src/StronglyTypedIds.Templates/long-dapper.typedid index 226f71367..3310653e6 100644 --- a/src/StronglyTypedIds.Templates/long-dapper.typedid +++ b/src/StronglyTypedIds.Templates/long-dapper.typedid @@ -1,6 +1,6 @@ partial struct PLACEHOLDERID { - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { diff --git a/src/StronglyTypedIds.Templates/long-efcore.typedid b/src/StronglyTypedIds.Templates/long-efcore.typedid index 34aa55c3c..ef88f8b7d 100644 --- a/src/StronglyTypedIds.Templates/long-efcore.typedid +++ b/src/StronglyTypedIds.Templates/long-efcore.typedid @@ -1,6 +1,6 @@ partial struct PLACEHOLDERID { - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) diff --git a/src/StronglyTypedIds.Templates/long-full.typedid b/src/StronglyTypedIds.Templates/long-full.typedid index 475870809..64470e776 100644 --- a/src/StronglyTypedIds.Templates/long-full.typedid +++ b/src/StronglyTypedIds.Templates/long-full.typedid @@ -37,7 +37,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -78,7 +78,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(long) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -195,7 +195,7 @@ => Value.TryFormat(destination, out charsWritten, format); #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -215,7 +215,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -226,7 +226,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid index 9db84a73a..ba37cc152 100644 --- a/src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid +++ b/src/StronglyTypedIds.Templates/long-newtonsoftjson.typedid @@ -1,7 +1,7 @@ [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID { - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/newid-full.typedid b/src/StronglyTypedIds.Templates/newid-full.typedid index 24b83177a..351d03ad9 100644 --- a/src/StronglyTypedIds.Templates/newid-full.typedid +++ b/src/StronglyTypedIds.Templates/newid-full.typedid @@ -38,7 +38,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -87,7 +87,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || typeToConvert == typeof(global::System.Guid) || base.CanConvert(typeToConvert); @@ -203,7 +203,7 @@ => Value.ToGuid().TryFormat(destination, out charsWritten, format); #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -221,7 +221,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -232,7 +232,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/nullablestring-full.typedid b/src/StronglyTypedIds.Templates/nullablestring-full.typedid index 383fc9877..bc3261571 100644 --- a/src/StronglyTypedIds.Templates/nullablestring-full.typedid +++ b/src/StronglyTypedIds.Templates/nullablestring-full.typedid @@ -52,7 +52,7 @@ (_, _) => string.CompareOrdinal(Value, other.Value), }; - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -86,7 +86,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -185,7 +185,7 @@ } #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -204,7 +204,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -215,7 +215,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/string-dapper.typedid b/src/StronglyTypedIds.Templates/string-dapper.typedid index 28b00a2c3..4af050343 100644 --- a/src/StronglyTypedIds.Templates/string-dapper.typedid +++ b/src/StronglyTypedIds.Templates/string-dapper.typedid @@ -1,6 +1,6 @@ partial struct PLACEHOLDERID { - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { diff --git a/src/StronglyTypedIds.Templates/string-efcore.typedid b/src/StronglyTypedIds.Templates/string-efcore.typedid index 2efb1eec2..6fd5fc403 100644 --- a/src/StronglyTypedIds.Templates/string-efcore.typedid +++ b/src/StronglyTypedIds.Templates/string-efcore.typedid @@ -1,6 +1,6 @@ partial struct PLACEHOLDERID { - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) diff --git a/src/StronglyTypedIds.Templates/string-full.typedid b/src/StronglyTypedIds.Templates/string-full.typedid index 14ec8101c..50fdc8ad3 100644 --- a/src/StronglyTypedIds.Templates/string-full.typedid +++ b/src/StronglyTypedIds.Templates/string-full.typedid @@ -52,7 +52,7 @@ (_, _) => string.CompareOrdinal(Value, other.Value), }; - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -88,7 +88,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -184,7 +184,7 @@ } #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -201,7 +201,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -212,7 +212,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid b/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid index 95bf00b8f..4711a24ec 100644 --- a/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid +++ b/src/StronglyTypedIds.Templates/string-newtonsoftjson.typedid @@ -1,7 +1,7 @@ [global::Newtonsoft.Json.JsonConverter(typeof(PLACEHOLDERIDNewtonsoftJsonConverter))] partial struct PLACEHOLDERID { - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/src/StronglyTypedIds/EmbeddedSources.Guid.cs b/src/StronglyTypedIds/EmbeddedSources.Guid.cs index c64f85d0e..7e905ab79 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Guid.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Guid.cs @@ -40,7 +40,7 @@ public override bool Equals(object? obj) /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -81,7 +81,7 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/src/StronglyTypedIds/EmbeddedSources.Int.cs b/src/StronglyTypedIds/EmbeddedSources.Int.cs index e731b68a4..6a21b986a 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Int.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Int.cs @@ -39,7 +39,7 @@ public override bool Equals(object? obj) /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -80,7 +80,7 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/src/StronglyTypedIds/EmbeddedSources.Long.cs b/src/StronglyTypedIds/EmbeddedSources.Long.cs index a825f35a8..0d1a47858 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Long.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Long.cs @@ -39,7 +39,7 @@ public override bool Equals(object? obj) /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -80,7 +80,7 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(long) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/src/StronglyTypedIds/EmbeddedSources.String.cs b/src/StronglyTypedIds/EmbeddedSources.String.cs index 6d0218631..d66f92566 100644 --- a/src/StronglyTypedIds/EmbeddedSources.String.cs +++ b/src/StronglyTypedIds/EmbeddedSources.String.cs @@ -54,7 +54,7 @@ public int CompareTo(PLACEHOLDERID other) (_, _) => string.CompareOrdinal(Value, other.Value), }; - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -90,7 +90,7 @@ public override bool CanConvertTo(global::System.ComponentModel.ITypeDescriptorC } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index b91ea5940..31775446e 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -49,7 +49,7 @@ /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -90,7 +90,7 @@ } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt index e3a28020b..e03bc8578 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt @@ -52,7 +52,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -101,7 +101,7 @@ namespace SomeNamespace } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || typeToConvert == typeof(global::System.Guid) || base.CanConvert(typeToConvert); @@ -217,7 +217,7 @@ namespace SomeNamespace => Value.ToGuid().TryFormat(destination, out charsWritten, format); #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, MyId value) { @@ -235,7 +235,7 @@ namespace SomeNamespace } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -246,7 +246,7 @@ namespace SomeNamespace ) { } } - public class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt index 6a3ac1695..04568ca04 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -55,7 +55,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -96,7 +96,7 @@ namespace SomeNamespace } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index 85612c116..1d170d01c 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -51,7 +51,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ namespace SomeNamespace } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index 85612c116..1d170d01c 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -51,7 +51,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ namespace SomeNamespace } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 802bd3a68..9b20ac148 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -51,7 +51,7 @@ namespace MyContracts.V1 /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ namespace MyContracts.V1 } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -268,7 +268,7 @@ namespace MyContracts.V2 /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -309,7 +309,7 @@ namespace MyContracts.V2 } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt index 282f46562..6681fb8ca 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt @@ -12,7 +12,7 @@ #nullable enable partial struct MyId { - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -38,7 +38,7 @@ #nullable enable partial struct MyId { - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, MyId value) { @@ -108,7 +108,7 @@ /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -149,7 +149,7 @@ } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt index b3cc80806..0b77f220b 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithoutBuiltIn.verified.txt @@ -12,7 +12,7 @@ #nullable enable partial struct MyId { - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -38,7 +38,7 @@ #nullable enable partial struct MyId { - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, MyId value) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index 0a6b497c5..d5fd29d80 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -53,7 +53,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -94,7 +94,7 @@ namespace SomeNamespace } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index c77b8adbd..e60ccd2fc 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -50,7 +50,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -91,7 +91,7 @@ namespace SomeNamespace } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index 1dc6c5144..8c8372976 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -57,7 +57,7 @@ namespace SomeNamespace /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -98,7 +98,7 @@ namespace SomeNamespace } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt index e5b53b542..1138a5f5e 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt @@ -50,7 +50,7 @@ /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -99,7 +99,7 @@ } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || typeToConvert == typeof(global::System.Guid) || base.CanConvert(typeToConvert); @@ -215,7 +215,7 @@ => Value.ToGuid().TryFormat(destination, out charsWritten, format); #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, MyId value) { @@ -233,7 +233,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -244,7 +244,7 @@ ) { } } - public class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class MyIdNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index 43a9b443b..7d81a0cee 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -48,7 +48,7 @@ /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); - public class MyIdTypeConverter : global::System.ComponentModel.TypeConverter + public partial class MyIdTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -89,7 +89,7 @@ } } - public class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class MyIdSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt index 73c8db3cd..b71fddfb9 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Guid.verified.txt @@ -52,7 +52,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -93,7 +93,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(global::System.Guid) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -214,7 +214,7 @@ => Value.TryFormat(destination, out charsWritten, format); #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -232,7 +232,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -243,7 +243,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt index 0e710dde9..fd1dcc935 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Int.verified.txt @@ -51,7 +51,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(int) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -209,7 +209,7 @@ => Value.TryFormat(destination, out charsWritten, format); #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -228,7 +228,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -239,7 +239,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt index a2ed10aff..46805531d 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_Long.verified.txt @@ -51,7 +51,7 @@ /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -92,7 +92,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(long) || typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -209,7 +209,7 @@ => Value.TryFormat(destination, out charsWritten, format); #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -229,7 +229,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -240,7 +240,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { diff --git a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt index b2cdf3a73..b17b95140 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/UnknownTemplateCodeFixProviderUnitTests.UsesBuiltInTemplates_String.verified.txt @@ -66,7 +66,7 @@ (_, _) => Value.CompareTo(other.Value), }; - public class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter + public partial class PLACEHOLDERIDTypeConverter : global::System.ComponentModel.TypeConverter { public override bool CanConvertFrom(global::System.ComponentModel.ITypeDescriptorContext? context, global::System.Type sourceType) { @@ -102,7 +102,7 @@ } } - public class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter + public partial class PLACEHOLDERIDSystemTextJsonConverter : global::System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(global::System.Type typeToConvert) => typeToConvert == typeof(string) || base.CanConvert(typeToConvert); @@ -198,7 +198,7 @@ } #endif - public class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler + public partial class DapperTypeHandler : global::Dapper.SqlMapper.TypeHandler { public override void SetValue(global::System.Data.IDbDataParameter parameter, PLACEHOLDERID value) { @@ -215,7 +215,7 @@ } } - public class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter + public partial class EfCoreValueConverter : global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter { public EfCoreValueConverter() : this(null) { } public EfCoreValueConverter(global::Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints? mappingHints = null) @@ -226,7 +226,7 @@ ) { } } - public class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter + public partial class PLACEHOLDERIDNewtonsoftJsonConverter : global::Newtonsoft.Json.JsonConverter { public override bool CanConvert(global::System.Type objectType) { From d4fe612da5809f289e074fe1497d7193151b0a15 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sun, 12 Nov 2023 12:48:29 +0000 Subject: [PATCH 46/47] Add comparison operators --- src/StronglyTypedIds.Templates/guid-full.typedid | 4 ++++ src/StronglyTypedIds.Templates/int-full.typedid | 4 ++++ src/StronglyTypedIds.Templates/long-full.typedid | 4 ++++ src/StronglyTypedIds.Templates/newid-full.typedid | 4 ++++ .../nullablestring-full.typedid | 4 ++++ src/StronglyTypedIds.Templates/string-full.typedid | 4 ++++ src/StronglyTypedIds/EmbeddedSources.Guid.cs | 4 ++++ src/StronglyTypedIds/EmbeddedSources.Int.cs | 4 ++++ src/StronglyTypedIds/EmbeddedSources.Long.cs | 4 ++++ src/StronglyTypedIds/EmbeddedSources.String.cs | 4 ++++ ...sts.CanGenerateDefaultIdInGlobalNamespace.verified.txt | 4 ++++ ...neratorTests.CanGenerateForCustomTemplate.verified.txt | 4 ++++ ...teGenericVeryNestedIdInFileScopeNamespace.verified.txt | 4 ++++ ...rTests.CanGenerateIdInFileScopedNamespace.verified.txt | 4 ++++ ...IdGeneratorTests.CanGenerateIdInNamespace.verified.txt | 4 ++++ ...rTests.CanGenerateMultipleIdsWithSameName.verified.txt | 8 ++++++++ ...s.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt | 4 ++++ ...s.CanGenerateNestedIdInFileScopeNamespace.verified.txt | 4 ++++ ...rTests.CanGenerateNonDefaultIdInNamespace.verified.txt | 4 ++++ ...nGenerateVeryNestedIdInFileScopeNamespace.verified.txt | 4 ++++ ...ltsWithCustomTemplateUsingGlobalAttribute.verified.txt | 4 ++++ ...eDefaultsWithTemplateUsingGlobalAttribute.verified.txt | 4 ++++ 22 files changed, 92 insertions(+) diff --git a/src/StronglyTypedIds.Templates/guid-full.typedid b/src/StronglyTypedIds.Templates/guid-full.typedid index a0fa78b5f..912d3dd7a 100644 --- a/src/StronglyTypedIds.Templates/guid-full.typedid +++ b/src/StronglyTypedIds.Templates/guid-full.typedid @@ -34,6 +34,10 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); diff --git a/src/StronglyTypedIds.Templates/int-full.typedid b/src/StronglyTypedIds.Templates/int-full.typedid index 520108330..c193f9f95 100644 --- a/src/StronglyTypedIds.Templates/int-full.typedid +++ b/src/StronglyTypedIds.Templates/int-full.typedid @@ -33,6 +33,10 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); diff --git a/src/StronglyTypedIds.Templates/long-full.typedid b/src/StronglyTypedIds.Templates/long-full.typedid index 64470e776..91931f272 100644 --- a/src/StronglyTypedIds.Templates/long-full.typedid +++ b/src/StronglyTypedIds.Templates/long-full.typedid @@ -33,6 +33,10 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); diff --git a/src/StronglyTypedIds.Templates/newid-full.typedid b/src/StronglyTypedIds.Templates/newid-full.typedid index 351d03ad9..fe05e3113 100644 --- a/src/StronglyTypedIds.Templates/newid-full.typedid +++ b/src/StronglyTypedIds.Templates/newid-full.typedid @@ -34,6 +34,10 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); diff --git a/src/StronglyTypedIds.Templates/nullablestring-full.typedid b/src/StronglyTypedIds.Templates/nullablestring-full.typedid index bc3261571..a538b9a58 100644 --- a/src/StronglyTypedIds.Templates/nullablestring-full.typedid +++ b/src/StronglyTypedIds.Templates/nullablestring-full.typedid @@ -41,6 +41,10 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) diff --git a/src/StronglyTypedIds.Templates/string-full.typedid b/src/StronglyTypedIds.Templates/string-full.typedid index 50fdc8ad3..d3c09f6ab 100644 --- a/src/StronglyTypedIds.Templates/string-full.typedid +++ b/src/StronglyTypedIds.Templates/string-full.typedid @@ -41,6 +41,10 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) diff --git a/src/StronglyTypedIds/EmbeddedSources.Guid.cs b/src/StronglyTypedIds/EmbeddedSources.Guid.cs index 7e905ab79..aaa504271 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Guid.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Guid.cs @@ -36,6 +36,10 @@ public override bool Equals(object? obj) public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); diff --git a/src/StronglyTypedIds/EmbeddedSources.Int.cs b/src/StronglyTypedIds/EmbeddedSources.Int.cs index 6a21b986a..d45771917 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Int.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Int.cs @@ -35,6 +35,10 @@ public override bool Equals(object? obj) public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); diff --git a/src/StronglyTypedIds/EmbeddedSources.Long.cs b/src/StronglyTypedIds/EmbeddedSources.Long.cs index 0d1a47858..9039432fb 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Long.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Long.cs @@ -35,6 +35,10 @@ public override bool Equals(object? obj) public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) => Value.CompareTo(other.Value); diff --git a/src/StronglyTypedIds/EmbeddedSources.String.cs b/src/StronglyTypedIds/EmbeddedSources.String.cs index d66f92566..6995e4673 100644 --- a/src/StronglyTypedIds/EmbeddedSources.String.cs +++ b/src/StronglyTypedIds/EmbeddedSources.String.cs @@ -43,6 +43,10 @@ public override bool Equals(object? obj) public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; + public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; + public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; /// public int CompareTo(PLACEHOLDERID other) diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index 31775446e..4a9bc014c 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -45,6 +45,10 @@ public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt index e03bc8578..067c0f71f 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt @@ -48,6 +48,10 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt index 04568ca04..6f0ce81ca 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -51,6 +51,10 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index 1d170d01c..6c6532eb4 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -47,6 +47,10 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index 1d170d01c..6c6532eb4 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -47,6 +47,10 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 9b20ac148..3c50bbfa7 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -47,6 +47,10 @@ namespace MyContracts.V1 public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); @@ -264,6 +268,10 @@ namespace MyContracts.V2 public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt index 6681fb8ca..42b1fb787 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt @@ -104,6 +104,10 @@ public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index d5fd29d80..606cde5e0 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -49,6 +49,10 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index e60ccd2fc..14f5bcde4 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -46,6 +46,10 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index 8c8372976..c515c0949 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -53,6 +53,10 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt index 1138a5f5e..e91449683 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt @@ -46,6 +46,10 @@ public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index 7d81a0cee..57239f576 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -44,6 +44,10 @@ public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); + public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; + public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; + public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; /// public int CompareTo(MyId other) => Value.CompareTo(other.Value); From 0cf31a1dfed565c948a0c721e3c6f7f5c2c32cdd Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Sun, 12 Nov 2023 13:34:45 +0000 Subject: [PATCH 47/47] Fix typo --- src/StronglyTypedIds.Templates/guid-full.typedid | 2 +- src/StronglyTypedIds.Templates/int-full.typedid | 2 +- src/StronglyTypedIds.Templates/long-full.typedid | 2 +- src/StronglyTypedIds.Templates/newid-full.typedid | 2 +- src/StronglyTypedIds.Templates/nullablestring-full.typedid | 2 +- src/StronglyTypedIds.Templates/string-full.typedid | 2 +- src/StronglyTypedIds/EmbeddedSources.Guid.cs | 2 +- src/StronglyTypedIds/EmbeddedSources.Int.cs | 2 +- src/StronglyTypedIds/EmbeddedSources.Long.cs | 2 +- src/StronglyTypedIds/EmbeddedSources.String.cs | 2 +- ...orTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt | 2 +- ...IdGeneratorTests.CanGenerateForCustomTemplate.verified.txt | 2 +- ...nerateGenericVeryNestedIdInFileScopeNamespace.verified.txt | 2 +- ...ratorTests.CanGenerateIdInFileScopedNamespace.verified.txt | 2 +- ...ypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt | 2 +- ...ratorTests.CanGenerateMultipleIdsWithSameName.verified.txt | 4 ++-- ...Tests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt | 2 +- ...Tests.CanGenerateNestedIdInFileScopeNamespace.verified.txt | 2 +- ...ratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt | 2 +- ...s.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt | 2 +- ...efaultsWithCustomTemplateUsingGlobalAttribute.verified.txt | 2 +- ...rrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt | 2 +- 22 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/StronglyTypedIds.Templates/guid-full.typedid b/src/StronglyTypedIds.Templates/guid-full.typedid index 912d3dd7a..00a1d2f47 100644 --- a/src/StronglyTypedIds.Templates/guid-full.typedid +++ b/src/StronglyTypedIds.Templates/guid-full.typedid @@ -34,7 +34,7 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/src/StronglyTypedIds.Templates/int-full.typedid b/src/StronglyTypedIds.Templates/int-full.typedid index c193f9f95..7fb419868 100644 --- a/src/StronglyTypedIds.Templates/int-full.typedid +++ b/src/StronglyTypedIds.Templates/int-full.typedid @@ -33,7 +33,7 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/src/StronglyTypedIds.Templates/long-full.typedid b/src/StronglyTypedIds.Templates/long-full.typedid index 91931f272..616e8a259 100644 --- a/src/StronglyTypedIds.Templates/long-full.typedid +++ b/src/StronglyTypedIds.Templates/long-full.typedid @@ -33,7 +33,7 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/src/StronglyTypedIds.Templates/newid-full.typedid b/src/StronglyTypedIds.Templates/newid-full.typedid index fe05e3113..d55f97530 100644 --- a/src/StronglyTypedIds.Templates/newid-full.typedid +++ b/src/StronglyTypedIds.Templates/newid-full.typedid @@ -34,7 +34,7 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/src/StronglyTypedIds.Templates/nullablestring-full.typedid b/src/StronglyTypedIds.Templates/nullablestring-full.typedid index a538b9a58..6c06d57c1 100644 --- a/src/StronglyTypedIds.Templates/nullablestring-full.typedid +++ b/src/StronglyTypedIds.Templates/nullablestring-full.typedid @@ -41,7 +41,7 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/src/StronglyTypedIds.Templates/string-full.typedid b/src/StronglyTypedIds.Templates/string-full.typedid index d3c09f6ab..be8e396f3 100644 --- a/src/StronglyTypedIds.Templates/string-full.typedid +++ b/src/StronglyTypedIds.Templates/string-full.typedid @@ -41,7 +41,7 @@ public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/src/StronglyTypedIds/EmbeddedSources.Guid.cs b/src/StronglyTypedIds/EmbeddedSources.Guid.cs index aaa504271..63ca8556a 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Guid.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Guid.cs @@ -36,7 +36,7 @@ public override bool Equals(object? obj) public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/src/StronglyTypedIds/EmbeddedSources.Int.cs b/src/StronglyTypedIds/EmbeddedSources.Int.cs index d45771917..2690ad76b 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Int.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Int.cs @@ -35,7 +35,7 @@ public override bool Equals(object? obj) public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/src/StronglyTypedIds/EmbeddedSources.Long.cs b/src/StronglyTypedIds/EmbeddedSources.Long.cs index 9039432fb..c3a3bd3f2 100644 --- a/src/StronglyTypedIds/EmbeddedSources.Long.cs +++ b/src/StronglyTypedIds/EmbeddedSources.Long.cs @@ -35,7 +35,7 @@ public override bool Equals(object? obj) public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/src/StronglyTypedIds/EmbeddedSources.String.cs b/src/StronglyTypedIds/EmbeddedSources.String.cs index 6995e4673..30d260a4e 100644 --- a/src/StronglyTypedIds/EmbeddedSources.String.cs +++ b/src/StronglyTypedIds/EmbeddedSources.String.cs @@ -43,7 +43,7 @@ public override bool Equals(object? obj) public static bool operator ==(PLACEHOLDERID a, PLACEHOLDERID b) => a.Equals(b); public static bool operator !=(PLACEHOLDERID a, PLACEHOLDERID b) => !(a == b); - public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => return a.CompareTo(b) > 0; + public static bool operator > (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) > 0; public static bool operator < (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) < 0; public static bool operator >= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) >= 0; public static bool operator <= (PLACEHOLDERID a, PLACEHOLDERID b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt index 4a9bc014c..4986c71ff 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateDefaultIdInGlobalNamespace.verified.txt @@ -45,7 +45,7 @@ public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt index 067c0f71f..b09689aaf 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateForCustomTemplate.verified.txt @@ -48,7 +48,7 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt index 6f0ce81ca..c55e78c8f 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateGenericVeryNestedIdInFileScopeNamespace.verified.txt @@ -51,7 +51,7 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt index 6c6532eb4..8a8530375 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInFileScopedNamespace.verified.txt @@ -47,7 +47,7 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt index 6c6532eb4..8a8530375 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateIdInNamespace.verified.txt @@ -47,7 +47,7 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt index 3c50bbfa7..9da3f1057 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleIdsWithSameName.verified.txt @@ -47,7 +47,7 @@ namespace MyContracts.V1 public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; @@ -268,7 +268,7 @@ namespace MyContracts.V2 public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt index 42b1fb787..ddcee0c20 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateMultipleTemplatesWithBuiltIn.verified.txt @@ -104,7 +104,7 @@ public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt index 606cde5e0..c2b59d42e 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNestedIdInFileScopeNamespace.verified.txt @@ -49,7 +49,7 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt index 14f5bcde4..db87dacf0 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateNonDefaultIdInNamespace.verified.txt @@ -46,7 +46,7 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt index c515c0949..776fbf1d3 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanGenerateVeryNestedIdInFileScopeNamespace.verified.txt @@ -53,7 +53,7 @@ namespace SomeNamespace public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt index e91449683..ed0410a74 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithCustomTemplateUsingGlobalAttribute.verified.txt @@ -46,7 +46,7 @@ public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0; diff --git a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt index 57239f576..6e458d2ff 100644 --- a/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt +++ b/test/StronglyTypedIds.Tests/Snapshots/StronglyTypedIdGeneratorTests.CanOverrideDefaultsWithTemplateUsingGlobalAttribute.verified.txt @@ -44,7 +44,7 @@ public static bool operator ==(MyId a, MyId b) => a.Equals(b); public static bool operator !=(MyId a, MyId b) => !(a == b); - public static bool operator > (MyId a, MyId b) => return a.CompareTo(b) > 0; + public static bool operator > (MyId a, MyId b) => a.CompareTo(b) > 0; public static bool operator < (MyId a, MyId b) => a.CompareTo(b) < 0; public static bool operator >= (MyId a, MyId b) => a.CompareTo(b) >= 0; public static bool operator <= (MyId a, MyId b) => a.CompareTo(b) <= 0;