From 46e618944242b9ab21edc4a3c848b6738b37c717 Mon Sep 17 00:00:00 2001 From: Timmy Date: Fri, 30 Jan 2026 19:32:50 +0100 Subject: [PATCH 1/4] Add debugger attributes --- Source/Common/OneOrMany{T}.cs | 9 ++++++++ Source/Common/Values{T1,T2,T3,T4,T5,T6,T7}.cs | 9 ++++++++ Source/Common/Values{T1,T2,T3,T4,T5,T6}.cs | 9 ++++++++ Source/Common/Values{T1,T2,T3,T4,T5}.cs | 9 ++++++++ Source/Common/Values{T1,T2,T3,T4}.cs | 9 ++++++++ Source/Common/Values{T1,T2,T3}.cs | 9 ++++++++ Source/Common/Values{T1,T2}.cs | 9 ++++++++ Source/Schema.NET/IValuesDebugView.cs | 22 +++++++++++++++++++ 8 files changed, 85 insertions(+) create mode 100644 Source/Schema.NET/IValuesDebugView.cs diff --git a/Source/Common/OneOrMany{T}.cs b/Source/Common/OneOrMany{T}.cs index f6d4adce..a0023e1c 100644 --- a/Source/Common/OneOrMany{T}.cs +++ b/Source/Common/OneOrMany{T}.cs @@ -3,6 +3,7 @@ namespace Schema.NET; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; @@ -12,11 +13,13 @@ namespace Schema.NET; /// /// The type of the values. /// +[DebuggerDisplay("{DebuggerDisplay,nq}")] [CollectionBuilder(typeof(OneOrManyBuilder), nameof(OneOrManyBuilder.Create))] #pragma warning disable CA1710 // Identifiers should have correct suffix. public readonly struct OneOrMany : IReadOnlyCollection, IValues, IEquatable> #pragma warning restore CA1710 // Identifiers should have correct suffix. { + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] private readonly T[]? collection; /// @@ -286,6 +289,12 @@ public bool Equals(OneOrMany other) /// /// A wrapping the current items. public ReadOnlySpan AsSpan() => this.collection.AsSpan(); + + /// + /// Gets the string to display in the debugger watches window for this instance. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"Length = {this.Count}"; } /// diff --git a/Source/Common/Values{T1,T2,T3,T4,T5,T6,T7}.cs b/Source/Common/Values{T1,T2,T3,T4,T5,T6,T7}.cs index bb252d9a..7046b635 100644 --- a/Source/Common/Values{T1,T2,T3,T4,T5,T6,T7}.cs +++ b/Source/Common/Values{T1,T2,T3,T4,T5,T6,T7}.cs @@ -3,6 +3,7 @@ namespace Schema.NET; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; @@ -16,6 +17,8 @@ namespace Schema.NET; /// The fifth type the values can take. /// The sixth type the values can take. /// The seventh type the values can take. +[DebuggerDisplay("{DebuggerDisplay,nq}")] +[DebuggerTypeProxy(typeof(IValuesDebugView))] [CollectionBuilder(typeof(ValuesBuilder), nameof(ValuesBuilder.Create))] public readonly struct Values : IReadOnlyCollection, IValues, IEquatable> { @@ -895,6 +898,12 @@ public bool Equals(Values other) /// public override int GetHashCode() => HashCode.Of(this.Value1).And(this.Value2).And(this.Value3).And(this.Value4).And(this.Value5).And(this.Value6).And(this.Value7); + + /// + /// Gets the string to display in the debugger watches window for this instance. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"Length = {this.Count}"; } public static partial class ValuesBuilder diff --git a/Source/Common/Values{T1,T2,T3,T4,T5,T6}.cs b/Source/Common/Values{T1,T2,T3,T4,T5,T6}.cs index 038be832..109bc49c 100644 --- a/Source/Common/Values{T1,T2,T3,T4,T5,T6}.cs +++ b/Source/Common/Values{T1,T2,T3,T4,T5,T6}.cs @@ -3,6 +3,7 @@ namespace Schema.NET; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; @@ -15,6 +16,8 @@ namespace Schema.NET; /// The fourth type the values can take. /// The fifth type the values can take. /// The sixth type the values can take. +[DebuggerDisplay("{DebuggerDisplay,nq}")] +[DebuggerTypeProxy(typeof(IValuesDebugView))] [CollectionBuilder(typeof(ValuesBuilder), nameof(ValuesBuilder.Create))] public readonly struct Values : IReadOnlyCollection, IValues, IEquatable> { @@ -775,6 +778,12 @@ public bool Equals(Values other) /// public override int GetHashCode() => HashCode.Of(this.Value1).And(this.Value2).And(this.Value3).And(this.Value4).And(this.Value5).And(this.Value6); + + /// + /// Gets the string to display in the debugger watches window for this instance. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"Length = {this.Count}"; } public static partial class ValuesBuilder diff --git a/Source/Common/Values{T1,T2,T3,T4,T5}.cs b/Source/Common/Values{T1,T2,T3,T4,T5}.cs index 2c2aa2bb..423df815 100644 --- a/Source/Common/Values{T1,T2,T3,T4,T5}.cs +++ b/Source/Common/Values{T1,T2,T3,T4,T5}.cs @@ -3,6 +3,7 @@ namespace Schema.NET; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; @@ -14,6 +15,8 @@ namespace Schema.NET; /// The third type the values can take. /// The fourth type the values can take. /// The fifth type the values can take. +[DebuggerDisplay("{DebuggerDisplay,nq}")] +[DebuggerTypeProxy(typeof(IValuesDebugView))] [CollectionBuilder(typeof(ValuesBuilder), nameof(ValuesBuilder.Create))] public readonly struct Values : IReadOnlyCollection, IValues, IEquatable> { @@ -659,6 +662,12 @@ public bool Equals(Values other) /// public override int GetHashCode() => HashCode.Of(this.Value1).And(this.Value2).And(this.Value3).And(this.Value4).And(this.Value5); + + /// + /// Gets the string to display in the debugger watches window for this instance. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"Length = {this.Count}"; } public static partial class ValuesBuilder diff --git a/Source/Common/Values{T1,T2,T3,T4}.cs b/Source/Common/Values{T1,T2,T3,T4}.cs index 0fa58635..6c4df29b 100644 --- a/Source/Common/Values{T1,T2,T3,T4}.cs +++ b/Source/Common/Values{T1,T2,T3,T4}.cs @@ -3,6 +3,7 @@ namespace Schema.NET; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; @@ -13,6 +14,8 @@ namespace Schema.NET; /// The second type the values can take. /// The third type the values can take. /// The fourth type the values can take. +[DebuggerDisplay("{DebuggerDisplay,nq}")] +[DebuggerTypeProxy(typeof(IValuesDebugView))] [CollectionBuilder(typeof(ValuesBuilder), nameof(ValuesBuilder.Create))] public readonly struct Values : IReadOnlyCollection, IValues, IEquatable> { @@ -547,6 +550,12 @@ public bool Equals(Values other) /// public override int GetHashCode() => HashCode.Of(this.Value1).And(this.Value2).And(this.Value3).And(this.Value4); + + /// + /// Gets the string to display in the debugger watches window for this instance. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"Length = {this.Count}"; } public static partial class ValuesBuilder diff --git a/Source/Common/Values{T1,T2,T3}.cs b/Source/Common/Values{T1,T2,T3}.cs index 1fee91e4..98a961d3 100644 --- a/Source/Common/Values{T1,T2,T3}.cs +++ b/Source/Common/Values{T1,T2,T3}.cs @@ -3,6 +3,7 @@ namespace Schema.NET; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; @@ -12,6 +13,8 @@ namespace Schema.NET; /// The first type the values can take. /// The second type the values can take. /// The third type the values can take. +[DebuggerDisplay("{DebuggerDisplay,nq}")] +[DebuggerTypeProxy(typeof(IValuesDebugView))] [CollectionBuilder(typeof(ValuesBuilder), nameof(ValuesBuilder.Create))] public readonly struct Values : IReadOnlyCollection, IValues, IEquatable> { @@ -438,6 +441,12 @@ public bool Equals(Values other) /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() => HashCode.Of(this.Value1).And(this.Value2).And(this.Value3); + + /// + /// Gets the string to display in the debugger watches window for this instance. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"Length = {this.Count}"; } public static partial class ValuesBuilder diff --git a/Source/Common/Values{T1,T2}.cs b/Source/Common/Values{T1,T2}.cs index 2c31e49f..484e0053 100644 --- a/Source/Common/Values{T1,T2}.cs +++ b/Source/Common/Values{T1,T2}.cs @@ -3,6 +3,7 @@ namespace Schema.NET; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; @@ -11,6 +12,8 @@ namespace Schema.NET; /// /// The first type the values can take. /// The second type the values can take. +[DebuggerDisplay("{DebuggerDisplay,nq}")] +[DebuggerTypeProxy(typeof(IValuesDebugView))] [CollectionBuilder(typeof(ValuesBuilder), nameof(ValuesBuilder.Create))] public readonly struct Values : IReadOnlyCollection, IValues, IEquatable> { @@ -334,6 +337,12 @@ public bool Equals(Values other) /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. /// public override int GetHashCode() => HashCode.Of(this.Value1).And(this.Value2); + + /// + /// Gets the string to display in the debugger watches window for this instance. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay => $"Length = {this.Count}"; } /// diff --git a/Source/Schema.NET/IValuesDebugView.cs b/Source/Schema.NET/IValuesDebugView.cs new file mode 100644 index 00000000..9011499e --- /dev/null +++ b/Source/Schema.NET/IValuesDebugView.cs @@ -0,0 +1,22 @@ +namespace Schema.NET; + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +internal sealed class IValuesDebugView +{ + private readonly IEnumerable collection; + + public IValuesDebugView(IEnumerable collection) + { + ArgumentNullException.ThrowIfNull(collection); + + this.collection = collection; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public object[] Items => this.collection.ToArray(); +} + From 1a99073355ee8d9e88c5506bde0623ad0e800673 Mon Sep 17 00:00:00 2001 From: Timmy Date: Fri, 30 Jan 2026 19:38:11 +0100 Subject: [PATCH 2/4] update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b4cf7522..81c5c46d 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ### Changes: - Add targets for .NET 8 - 10 - Add support for [collection expressions](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/collection-expressions) +- Added debugging attributes [#48](https://github.com/TimmyMC/Schema.NET/pull/48) - Performance improvements ### Why the fork? > I created this fork for to use in a large webshop, I initially wanted the package to target .net 8.
From 5d21b98b695d56e15fc3ea7bc8de9648f268499a Mon Sep 17 00:00:00 2001 From: Timmy Date: Fri, 30 Jan 2026 20:19:45 +0100 Subject: [PATCH 3/4] Add debugger attributes --- Schema.NET.sln | 1 + Source/{Schema.NET => Common}/IValuesDebugView.cs | 0 Source/Common/OneOrMany{T}.cs | 3 +++ 3 files changed, 4 insertions(+) rename Source/{Schema.NET => Common}/IValuesDebugView.cs (100%) diff --git a/Schema.NET.sln b/Schema.NET.sln index b8f4625d..9fea6c8d 100644 --- a/Schema.NET.sln +++ b/Schema.NET.sln @@ -107,6 +107,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{AF228B Source\Common\Values{T1,T2,T3,T4}.cs = Source\Common\Values{T1,T2,T3,T4}.cs Source\Common\Values{T1,T2,T3}.cs = Source\Common\Values{T1,T2,T3}.cs Source\Common\Values{T1,T2}.cs = Source\Common\Values{T1,T2}.cs + Source\Common\IValuesDebugView.cs = Source\Common\IValuesDebugView.cs EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schema.NET.Updater", "Tools\Schema.NET.Updater\Schema.NET.Updater.csproj", "{8923F9E2-4BB8-45F9-9A85-863F381B46EE}" diff --git a/Source/Schema.NET/IValuesDebugView.cs b/Source/Common/IValuesDebugView.cs similarity index 100% rename from Source/Schema.NET/IValuesDebugView.cs rename to Source/Common/IValuesDebugView.cs diff --git a/Source/Common/OneOrMany{T}.cs b/Source/Common/OneOrMany{T}.cs index a0023e1c..0added2f 100644 --- a/Source/Common/OneOrMany{T}.cs +++ b/Source/Common/OneOrMany{T}.cs @@ -110,18 +110,21 @@ public OneOrMany(IEnumerable collection) : this(collection.Cast().T /// /// Gets the number of elements contained in the . /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] public int Count => this.collection?.Length ?? 0; /// /// Gets a value indicating whether this instance has a single item value. /// /// true if this instance has a single item value; otherwise, false. + [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool HasOne { get; } /// /// Gets a value indicating whether this instance has more than one value. /// /// true if this instance has more than one value; otherwise, false. + [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool HasMany => this.collection?.Length > 1; /// From 1e6bb532d070367624baccbaae21ffceb598832e Mon Sep 17 00:00:00 2001 From: Timmy Date: Sat, 31 Jan 2026 08:46:32 +0100 Subject: [PATCH 4/4] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 81c5c46d..f007a6f5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # (Temporary?) Fork of [Schema.NET](https://github.com/RehanSaeed/Schema.NET) ### Changes: - Add targets for .NET 8 - 10 -- Add support for [collection expressions](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/collection-expressions) +- Removed targets for EOL .NET versions and .Net Framework +- Add support for [collection expressions](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/collection-expressions) [#36](https://github.com/TimmyMC/Schema.NET/pull/36) - Added debugging attributes [#48](https://github.com/TimmyMC/Schema.NET/pull/48) - Performance improvements ### Why the fork?