From e0dff35a64445cc8fd634acc199162d3ae4ac903 Mon Sep 17 00:00:00 2001 From: Shawn LaMountain Date: Mon, 6 Jul 2026 17:56:35 -0400 Subject: [PATCH 1/3] Added Equality Helper --- README.md | 3 + .../Helpers/EqualityHelper.cs | 109 ++++++++++++++++++ .../ThunderDesign.Net-PCL.ToolBox.csproj | 6 +- 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/ThunderDesign.Net-PCL.ToolBox/Helpers/EqualityHelper.cs diff --git a/README.md b/README.md index da6e87d..a17e60d 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,9 @@ A set of core methods and classes to ease every days .NET development tasks. - StringExtentions - TypeExtentions +- Helpers + - EqualityHelper + ---- ## Installation diff --git a/src/ThunderDesign.Net-PCL.ToolBox/Helpers/EqualityHelper.cs b/src/ThunderDesign.Net-PCL.ToolBox/Helpers/EqualityHelper.cs new file mode 100644 index 0000000..e90b2bc --- /dev/null +++ b/src/ThunderDesign.Net-PCL.ToolBox/Helpers/EqualityHelper.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace ThunderDesign.Net_PCL.ToolBox.Helpers +{ + public static class EqualityHelper + { + public static bool Equality(ref T backingStore, T value) + { + if (typeof(T) == typeof(string)) + { + return StringEquality(ref backingStore, value); + } + else if (typeof(IStructuralEquatable).IsAssignableFrom(typeof(T))) + { + return StructureEquality(ref backingStore, value); + } + else if (typeof(T).IsValueType) + { + return ValueEquality(ref backingStore, value); + } + else + { + return ReferenceEquality(ref backingStore, value); + } + } + + /// + /// Checks for equality between two string values. + /// + /// + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool StringEquality(ref T backingStore, T value) + { + if (typeof(T) != typeof(string)) + { + throw new InvalidOperationException($"Type: {typeof(T)} cannot be used with string types."); + } + + return string.Equals(backingStore as string, value as string, StringComparison.Ordinal); + } + + /// + /// Checks for equality between two structural values. + /// + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool StructureEquality(ref T backingStore, T value) + { + if (!typeof(IStructuralEquatable).IsAssignableFrom(typeof(T))) + { + throw new InvalidOperationException($"Type: {typeof(T)} cannot be used with structural types."); + } + else if (backingStore == null && value == null) + { + return true; + } + else if (backingStore == null || value == null) + { + return false; + } + + var structuralEquatable = backingStore as IStructuralEquatable; + return structuralEquatable.Equals(value, StructuralComparisons.StructuralEqualityComparer); + } + + /// + /// Checks for equality between two value types. + /// + /// + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ValueEquality(ref T backingStore, T value) + { + if (!typeof(T).IsValueType) + { + throw new InvalidOperationException($"Type: {typeof(T)} cannot be used with value types."); + } + + return EqualityComparer.Default.Equals(backingStore, value); + } + + /// + /// Checks for equality between two reference types. + /// + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ReferenceEquality(ref T backingStore, T value) + { + return ReferenceEquals(backingStore, value); + } + } +} diff --git a/src/ThunderDesign.Net-PCL.ToolBox/ThunderDesign.Net-PCL.ToolBox.csproj b/src/ThunderDesign.Net-PCL.ToolBox/ThunderDesign.Net-PCL.ToolBox.csproj index e93364f..0ffea27 100644 --- a/src/ThunderDesign.Net-PCL.ToolBox/ThunderDesign.Net-PCL.ToolBox.csproj +++ b/src/ThunderDesign.Net-PCL.ToolBox/ThunderDesign.Net-PCL.ToolBox.csproj @@ -1,4 +1,4 @@ - + netstandard1.0;netstandard2.0;net461 @@ -8,6 +8,10 @@ NETSTANDARD1_4 + + + + True From e652abb411abc1414531efa754d4dfd0a10e47d2 Mon Sep 17 00:00:00 2001 From: Shawn LaMountain Date: Mon, 6 Jul 2026 18:47:53 -0400 Subject: [PATCH 2/3] updated CI/CD --- .github/workflows/CD.yml | 20 ++++++++++++-- .github/workflows/CI.yml | 2 +- src/ThunderDesign.Net-PCL.Toolbox.nuspec.in | 29 +++++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/ThunderDesign.Net-PCL.Toolbox.nuspec.in diff --git a/.github/workflows/CD.yml b/.github/workflows/CD.yml index 1200ed6..545e1af 100644 --- a/.github/workflows/CD.yml +++ b/.github/workflows/CD.yml @@ -24,7 +24,7 @@ env: jobs: pack: - runs-on: [windows-2019] + runs-on: [windows-latest] steps: - name: Checkout @@ -44,8 +44,24 @@ jobs: - name: Restore NuGet packages.sln run: nuget restore ./src/${{ env.FILE_NAME}}.sln + - name: Build Solution + run: msbuild ./src/${{ env.FILE_NAME}}.sln /p:Configuration=Release + + - name: Prepare .nuspec + run: | + $nuspecPath = "src/${{ env.FILE_NAME }}.nuspec.in" + $nuspec = Get-Content $nuspecPath + $nuspec = $nuspec -replace '\$\{\{ env.FILE_NAME \}\}', '${{ env.FILE_NAME }}' + $nuspec = $nuspec -replace '\$\{\{ env.TITLE \}\}', '${{ env.TITLE }}' + $nuspec = $nuspec -replace '\$\{\{ env.DESCRIPTION \}\}', '${{ env.DESCRIPTION }}' + $nuspec = $nuspec -replace '\$\{\{ env.TAGS \}\}', '${{ env.TAGS }}' + $nuspec = $nuspec -replace '\$\{\{ env.GITHUB_URL \}\}', '${{ env.GITHUB_URL }}' + $nuspec = $nuspec -replace '\$\{\{ env.REPOSITORY_URL \}\}', '${{ env.REPOSITORY_URL }}' + Set-Content ThunderDesign.Net-PCL.nuspec $nuspec + shell: pwsh + - name: Create NuGet Package - run: msbuild ./src/${{ env.FILE_NAME}}.sln -t:pack /p:VersionPrefix=${{ github.event.release.tag_name }} /p:Configuration=Release /p:Title="${{ env.TITLE }}" /p:Description="${{ env.DESCRIPTION }}" /p:PackageTags="${{ env.TAGS }}" /p:Authors=ThunderDesign /p:PackageProjectUrl=${{ env.GITHUB_URL }} /p:PackageLicenseExpression=MIT /p:RepositoryType=git /p:RepositoryUrl=${{ env.REPOSITORY_URL }} /p:PackageReleaseNotes="See ${{ env.REPOSITORY_URL }}/releases/tag/${{ github.event.release.tag_name }}" /p:PackageReadmeFile="README.md" /p:PackageOutputPath=${{ env.PACKAGE_OUTPUT_DIRECTORY}} + run: nuget pack ThunderDesign.Net-PCL.nuspec -Version ${{ github.event.release.tag_name }} -OutputDirectory ${{ env.PACKAGE_OUTPUT_DIRECTORY }} - name: Archive NuGet Package uses: actions/upload-artifact@v2.3.1 diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d534427..72f5326 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -14,7 +14,7 @@ env: jobs: build: - runs-on: [windows-2019] + runs-on: [windows-latest] steps: - name: Checkout diff --git a/src/ThunderDesign.Net-PCL.Toolbox.nuspec.in b/src/ThunderDesign.Net-PCL.Toolbox.nuspec.in new file mode 100644 index 0000000..e3dfc7d --- /dev/null +++ b/src/ThunderDesign.Net-PCL.Toolbox.nuspec.in @@ -0,0 +1,29 @@ + + + + ${{ env.FILE_NAME }} + $version$ + ${{ env.TITLE }} + ThunderDesign + ThunderDesign + false + MIT + ${{ env.GITHUB_URL }} + ${{ env.DESCRIPTION }} + See ${{ env.REPOSITORY_URL }}/releases/tag/$version$ + ${{ env.TAGS }} + + README.md + + + + + + + + + + + + + \ No newline at end of file From 4d63287f941e48412eb78d9656ccd2188d5fb619 Mon Sep 17 00:00:00 2001 From: Shawn LaMountain Date: Mon, 6 Jul 2026 19:05:13 -0400 Subject: [PATCH 3/3] updated CI/CD --- .github/workflows/CD.yml | 3 +++ .github/workflows/CI.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/CD.yml b/.github/workflows/CD.yml index 545e1af..663482b 100644 --- a/.github/workflows/CD.yml +++ b/.github/workflows/CD.yml @@ -30,6 +30,9 @@ jobs: - name: Checkout uses: actions/checkout@v2 + - name: Install .NET Framework 4.6.1 Developer Pack + run: choco install netfx-4.6.1-devpack -y + - name: Setup .NET 2.0 uses: actions/setup-dotnet@v1 with: diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 72f5326..24978dc 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -20,6 +20,9 @@ jobs: - name: Checkout uses: actions/checkout@v2 + - name: Install .NET Framework 4.6.1 Developer Pack + run: choco install netfx-4.6.1-devpack -y + - name: Setup .NET 2.0 uses: actions/setup-dotnet@v1 with: