diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 4a649ba..34d84e9 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -2,7 +2,7 @@
## Project Overview
-SharedCode is a multi-project .NET 9 solution that provides reusable utility libraries
+SharedCode is a multi-project .NET solution that provides reusable utility libraries
published as individual NuGet packages. Each project corresponds to one NuGet package:
| Project | NuGet Package | Purpose |
@@ -34,7 +34,9 @@ dotnet test --logger GitHubActions --verbosity normal SharedCode.sln
### Language & Framework
-- **Target framework**: `net9.0`
+- **Target frameworks**:
+ - Primary/current: `.NET 10` (`net10.0`)
+ - Compatibility targets: `.NET 9` (`net9.0`), `.NET 8` (`net8.0`), and `.NET Standard 2.0/2.1` where applicable
- **Language version**: `preview` (latest C# features enabled)
- **Nullable reference types**: enabled (`enable`)
- **Implicit usings**: enabled
diff --git a/.github/prompts/create-module.prompt.md b/.github/prompts/create-module.prompt.md
index 9f2257e..c6a3fa4 100644
--- a/.github/prompts/create-module.prompt.md
+++ b/.github/prompts/create-module.prompt.md
@@ -27,7 +27,7 @@ belong here.
A library of [short description] shared for free use to help with common scenarios.
shared code, c#, [relevant tags]
SharedCode.
- net9.0
+ net9.0;net10.0
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index e09e401..e4841f4 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -19,7 +19,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Run tests
run: dotnet test --logger GitHubActions SharedCode.sln
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index eaa20aa..d005744 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -17,9 +17,9 @@ jobs:
- uses: actions/checkout@v3
- name: Setup .NET
- uses: actions/setup-dotnet@v2
+ uses: actions/setup-dotnet@v4
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Run Tests
run: dotnet test --logger GitHubActions --verbosity normal SharedCode.sln
@@ -34,9 +34,9 @@ jobs:
- uses: actions/checkout@v3
- name: Setup .NET
- uses: actions/setup-dotnet@v2
+ uses: actions/setup-dotnet@v4
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Bump version and push tag
id: tag_version
@@ -73,9 +73,9 @@ jobs:
name: PackedLib
- name: Setup .NET
- uses: actions/setup-dotnet@v2
+ uses: actions/setup-dotnet@v4
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Push Package to GitHub
run: dotnet nuget push --api-key ${{secrets.GITHUB_TOKEN}} --source "https://nuget.pkg.github.com/improvgroup/index.json" *.nupkg
@@ -93,9 +93,9 @@ jobs:
name: PackedLib
- name: Setup .NET
- uses: actions/setup-dotnet@v2
+ uses: actions/setup-dotnet@v4
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Push Package to NuGet
run: dotnet nuget push --api-key ${{secrets.NUGET_API_KEY}} --source "https://api.nuget.org/v3/index.json" *.nupkg
diff --git a/Directory.Build.props b/Directory.Build.props
index 4541e31..00a7305 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -24,7 +24,7 @@
true
preview
en-US
- $(NoWarn);CA1014
+ $(NoWarn);CA1014;NU1510
enable
share.png
MIT
@@ -100,6 +100,12 @@
+
+
+
+
+ false
+
diff --git a/README.md b/README.md
index ad0869e..7f2860d 100644
--- a/README.md
+++ b/README.md
@@ -42,19 +42,20 @@ in only what you need.
| Package | NuGet | Target Frameworks | Description |
|---|---|---|---|
-| `SharedCode.Core` | [](https://www.nuget.org/packages/SharedCode.Core) | `netstandard2.0`, `netstandard2.1`, `net8.0`, `net9.0` | Core utilities: extensions, specifications, domain primitives, security, threading, reactive |
-| `SharedCode.Data` | [](https://www.nuget.org/packages/SharedCode.Data) | `netstandard2.0`, `netstandard2.1`, `net8.0`, `net9.0` | Framework-agnostic data access abstractions: repository pattern, paging, query results |
-| `SharedCode.Data.CosmosDb` | [](https://www.nuget.org/packages/SharedCode.Data.CosmosDb) | `net8.0`, `net9.0` | Azure Cosmos DB integration and helpers |
-| `SharedCode.Data.EntityFramework` | [](https://www.nuget.org/packages/SharedCode.Data.EntityFramework) | `net8.0`, `net9.0` | Entity Framework Core integration: auditable contexts, EF repository, specifications |
-| `SharedCode.DependencyInjection` | [](https://www.nuget.org/packages/SharedCode.DependencyInjection) | `netstandard2.0`, `netstandard2.1`, `net8.0`, `net9.0` | DI assembly scanning and auto-registration via `IDependencyRegister` |
-| `SharedCode.MediatR` | [](https://www.nuget.org/packages/SharedCode.MediatR) | `net8.0`, `net9.0` | MediatR command/query abstractions and pipeline helpers |
-| `SharedCode.Web` | [](https://www.nuget.org/packages/SharedCode.Web) | `net9.0` | ASP.NET Core helpers: base controller, resilient HTTP client setup, health checks |
-| `SharedCode.Windows.WPF` | [](https://www.nuget.org/packages/SharedCode.Windows.WPF) | `net9.0-windows10.0.22621.0` | WPF helpers: `BindableBase`, value converters, attached properties, MVVM mediator |
+| `SharedCode.Core` | [](https://www.nuget.org/packages/SharedCode.Core) | `netstandard2.0`, `netstandard2.1`, `net8.0`, `net9.0`, `net10.0` | Core utilities: extensions, specifications, domain primitives, security, threading, reactive |
+| `SharedCode.Data` | [](https://www.nuget.org/packages/SharedCode.Data) | `netstandard2.0`, `netstandard2.1`, `net8.0`, `net9.0`, `net10.0` | Framework-agnostic data access abstractions: repository pattern, paging, query results |
+| `SharedCode.Data.CosmosDb` | [](https://www.nuget.org/packages/SharedCode.Data.CosmosDb) | `net8.0`, `net9.0`, `net10.0` | Azure Cosmos DB integration and helpers |
+| `SharedCode.Data.EntityFramework` | [](https://www.nuget.org/packages/SharedCode.Data.EntityFramework) | `net8.0`, `net9.0`, `net10.0` | Entity Framework Core integration: auditable contexts, EF repository, specifications |
+| `SharedCode.DependencyInjection` | [](https://www.nuget.org/packages/SharedCode.DependencyInjection) | `netstandard2.0`, `netstandard2.1`, `net8.0`, `net9.0`, `net10.0` | DI assembly scanning and auto-registration via `IDependencyRegister` |
+| `SharedCode.MediatR` | [](https://www.nuget.org/packages/SharedCode.MediatR) | `net8.0`, `net9.0`, `net10.0` | MediatR command/query abstractions and pipeline helpers |
+| `SharedCode.Web` | [](https://www.nuget.org/packages/SharedCode.Web) | `net9.0`, `net10.0` | ASP.NET Core helpers: base controller, resilient HTTP client setup, health checks |
+| `SharedCode.Windows.WPF` | [](https://www.nuget.org/packages/SharedCode.Windows.WPF) | `net9.0-windows10.0.22621.0`, `net10.0-windows10.0.22621.0` | WPF helpers: `BindableBase`, value converters, attached properties, MVVM mediator |
---
## Requirements
+- [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) (for `net10.0` targets)
- [.NET 9 SDK](https://dotnet.microsoft.com/download/dotnet/9.0) (for `net9.0` targets)
- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) (for `net8.0` targets)
- .NET Standard 2.0 / 2.1 targets are compatible with .NET Framework 4.6.1+ and .NET Core 2.0+
@@ -100,7 +101,7 @@ Install-Package SharedCode.Windows.WPF
[](https://www.nuget.org/packages/SharedCode.Core)
Core utilities and domain primitives that are shared across all other packages. Targets
-`netstandard2.0`, `netstandard2.1`, `net8.0`, and `net9.0`.
+`netstandard2.0`, `netstandard2.1`, `net8.0`, `net9.0`, and `net10.0`.
**Highlights**
@@ -137,7 +138,7 @@ public sealed class ActiveUsersSpec : Specification
[](https://www.nuget.org/packages/SharedCode.Data)
Framework-agnostic data access abstractions. Targets `netstandard2.0`, `netstandard2.1`,
-`net8.0`, and `net9.0`.
+`net8.0`, `net9.0`, and `net10.0`.
**Highlights**
@@ -170,7 +171,7 @@ public class UserService
Azure Cosmos DB integration built on top of the official
[Microsoft.Azure.Cosmos](https://www.nuget.org/packages/Microsoft.Azure.Cosmos) SDK.
-Targets `net8.0` and `net9.0`.
+Targets `net8.0`, `net9.0`, and `net10.0`.
**Highlights**
@@ -183,7 +184,7 @@ Targets `net8.0` and `net9.0`.
[](https://www.nuget.org/packages/SharedCode.Data.EntityFramework)
-Entity Framework Core integration. Targets `net8.0` and `net9.0`.
+Entity Framework Core integration. Targets `net8.0`, `net9.0`, and `net10.0`.
**Highlights**
@@ -213,7 +214,7 @@ services.AddDbContext(options =>
[](https://www.nuget.org/packages/SharedCode.DependencyInjection)
Assembly scanning and automatic service registration. Targets `netstandard2.0`,
-`netstandard2.1`, `net8.0`, and `net9.0`.
+`netstandard2.1`, `net8.0`, `net9.0`, and `net10.0`.
**Highlights**
@@ -241,8 +242,8 @@ public class MyServiceRegistrar : IDependencyRegister
[](https://www.nuget.org/packages/SharedCode.MediatR)
-[MediatR](https://github.com/jbogard/MediatR) pipeline abstractions. Targets `net8.0` and
-`net9.0`.
+[MediatR](https://github.com/jbogard/MediatR) pipeline abstractions. Targets `net8.0`,
+`net9.0`, and `net10.0`.
**Highlights**
@@ -277,7 +278,7 @@ services.AddSharedCodeMediatR(typeof(Program).Assembly);
[](https://www.nuget.org/packages/SharedCode.Web)
-ASP.NET Core helpers. Targets `net9.0`.
+ASP.NET Core helpers. Targets `net9.0` and `net10.0`.
**Highlights**
@@ -303,7 +304,7 @@ public class UsersController : BaseController
[](https://www.nuget.org/packages/SharedCode.Windows.WPF)
-WPF helpers targeting `net9.0-windows10.0.22621.0`.
+WPF helpers targeting `net9.0-windows10.0.22621.0` and `net10.0-windows10.0.22621.0`.
**Highlights**
@@ -334,8 +335,9 @@ dotnet build SharedCode.sln
dotnet test SharedCode.sln
```
-The solution targets **.NET 9** for the library projects. The WPF project additionally requires
-Windows 10 SDK version 10.0.19041.0 or later.
+The solution targets **.NET 8, .NET 9, and .NET 10** for library projects (plus .NET Standard
+2.0/2.1 compatibility for selected packages). The WPF project additionally requires Windows 10 SDK
+version 10.0.19041.0 or later.
---
diff --git a/SharedCode.Core.Tests/Calendar/DateTimeExtensionsTests.cs b/SharedCode.Core.Tests/Calendar/DateTimeExtensionsTests.cs
index 840425a..b508ce1 100644
--- a/SharedCode.Core.Tests/Calendar/DateTimeExtensionsTests.cs
+++ b/SharedCode.Core.Tests/Calendar/DateTimeExtensionsTests.cs
@@ -6,6 +6,7 @@ namespace SharedCode.Tests.Calendar;
using SharedCode.Calendar;
using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
///
/// The date time extensions tests class
@@ -26,6 +27,16 @@ public class DateTimeExtensionsTests
///
private DateTime originalDateTime;
+ ///
+ /// The original culture before test execution.
+ ///
+ private CultureInfo? originalCulture;
+
+ ///
+ /// The original UI culture before test execution.
+ ///
+ private CultureInfo? originalUiCulture;
+
[TestMethod]
[DataRow(5, 2022, 12, 11, 2022, 12, 19)]
[DataRow(3, 2022, 12, 10, 2022, 12, 15)]
@@ -61,7 +72,7 @@ public void AddWorkdays_SkipsWeekends()
public void Can_Get_Full_Long_Date_Time_String()
{
var result = this.originalDateTime.ToStringFormat(() => DateTimeFormat.FullLongDateTime);
- Assert.AreEqual("Sunday, March 11, 1984 2:30:58 AM", result);
+ Assert.AreEqual("Sunday, March 11, 1984 2:30:58 AM", NormalizeWhitespace(result));
}
///
@@ -71,7 +82,7 @@ public void Can_Get_Full_Long_Date_Time_String()
public void Can_Get_Full_Short_Date_Time_String()
{
var result = this.originalDateTime.ToStringFormat(() => DateTimeFormat.FullShortDateTime);
- Assert.AreEqual("Sunday, March 11, 1984 2:30 AM", result);
+ Assert.AreEqual("Sunday, March 11, 1984 2:30 AM", NormalizeWhitespace(result));
}
///
@@ -81,7 +92,7 @@ public void Can_Get_Full_Short_Date_Time_String()
public void Can_Get_General_Long_Date_Time_String()
{
var result = this.originalDateTime.ToStringFormat(() => DateTimeFormat.GeneralLongDateTime);
- Assert.AreEqual("3/11/1984 2:30:58 AM", result);
+ Assert.AreEqual("3/11/1984 2:30:58 AM", NormalizeWhitespace(result));
}
///
@@ -91,7 +102,7 @@ public void Can_Get_General_Long_Date_Time_String()
public void Can_Get_General_Short_Date_Time_String()
{
var result = this.originalDateTime.ToStringFormat(() => DateTimeFormat.GeneralShortDateTime);
- Assert.AreEqual("3/11/1984 2:30 AM", result);
+ Assert.AreEqual("3/11/1984 2:30 AM", NormalizeWhitespace(result));
}
///
@@ -111,7 +122,7 @@ public void Can_Get_Long_Date_String()
public void Can_Get_Long_Time_String()
{
var result = this.originalDateTime.ToStringFormat(() => DateTimeFormat.LongTime);
- Assert.AreEqual("2:30:58 AM", result);
+ Assert.AreEqual("2:30:58 AM", NormalizeWhitespace(result));
}
///
@@ -171,7 +182,7 @@ public void Can_Get_Short_Date_String()
public void Can_Get_Short_Time_String()
{
var result = this.originalDateTime.ToStringFormat(() => DateTimeFormat.ShortTime);
- Assert.AreEqual("2:30 AM", result);
+ Assert.AreEqual("2:30 AM", NormalizeWhitespace(result));
}
///
@@ -219,7 +230,14 @@ public void Can_Get_Year_Month_Upper_Case_String()
/// Initializes the test case.
///
[TestInitialize]
- public void InitTestCase() => this.originalDateTime = new DateTime(Year, Month, Day, Hour, Minute, Second);
+ public void InitTestCase()
+ {
+ this.originalCulture = CultureInfo.CurrentCulture;
+ this.originalUiCulture = CultureInfo.CurrentUICulture;
+ CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
+ CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
+ this.originalDateTime = new DateTime(Year, Month, Day, Hour, Minute, Second);
+ }
///
/// Teardowns the test case.
@@ -232,5 +250,17 @@ public void TeardownTestCase()
{
GC.SuppressFinalize(this.originalDateTime);
}
+
+ if (this.originalCulture is not null)
+ {
+ CultureInfo.CurrentCulture = this.originalCulture;
+ }
+
+ if (this.originalUiCulture is not null)
+ {
+ CultureInfo.CurrentUICulture = this.originalUiCulture;
+ }
}
+
+ private static string NormalizeWhitespace(string value) => value.Replace('\u202F', ' ');
}
diff --git a/SharedCode.Core.Tests/Core.Tests.csproj b/SharedCode.Core.Tests/Core.Tests.csproj
index 3857501..4e86630 100644
--- a/SharedCode.Core.Tests/Core.Tests.csproj
+++ b/SharedCode.Core.Tests/Core.Tests.csproj
@@ -6,7 +6,7 @@
false
false
SharedCode.Tests
- net9.0
+ net9.0;net10.0
diff --git a/SharedCode.Core/Core.csproj b/SharedCode.Core/Core.csproj
index 8ef53d6..02cee0c 100644
--- a/SharedCode.Core/Core.csproj
+++ b/SharedCode.Core/Core.csproj
@@ -3,7 +3,7 @@
SharedCode.Core
latest
SharedCode
- netstandard2.0;netstandard2.1;net8.0;net9.0
+ netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0
diff --git a/SharedCode.Data.CosmosDb/Data.CosmosDb.csproj b/SharedCode.Data.CosmosDb/Data.CosmosDb.csproj
index 014b462..954c4a8 100644
--- a/SharedCode.Data.CosmosDb/Data.CosmosDb.csproj
+++ b/SharedCode.Data.CosmosDb/Data.CosmosDb.csproj
@@ -2,7 +2,7 @@
SharedCode.Data.CosmosDb
SharedCode.Data.CosmosDb
- net8.0;net9.0
+ net8.0;net9.0;net10.0
diff --git a/SharedCode.Data.EntityFramework/Data.EntityFramework.csproj b/SharedCode.Data.EntityFramework/Data.EntityFramework.csproj
index 8232b2d..1ccfff4 100644
--- a/SharedCode.Data.EntityFramework/Data.EntityFramework.csproj
+++ b/SharedCode.Data.EntityFramework/Data.EntityFramework.csproj
@@ -2,7 +2,7 @@
SharedCode.Data.EntityFramework
SharedCode.Data.EntityFramework
- net8.0;net9.0
+ net8.0;net9.0;net10.0
diff --git a/SharedCode.Data.Tests/Data.Tests.csproj b/SharedCode.Data.Tests/Data.Tests.csproj
index d99805b..d0ceece 100644
--- a/SharedCode.Data.Tests/Data.Tests.csproj
+++ b/SharedCode.Data.Tests/Data.Tests.csproj
@@ -6,7 +6,7 @@
false
false
SharedCode.Data.Tests
- net9.0
+ net9.0;net10.0
diff --git a/SharedCode.Data/Data.csproj b/SharedCode.Data/Data.csproj
index 648f5fa..1b8cb35 100644
--- a/SharedCode.Data/Data.csproj
+++ b/SharedCode.Data/Data.csproj
@@ -3,7 +3,7 @@
SharedCode.Data
latest
SharedCode.Data
- netstandard2.0;netstandard2.1;net8.0;net9.0
+ netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0
diff --git a/SharedCode.DependencyInjection/DependencyInjection.csproj b/SharedCode.DependencyInjection/DependencyInjection.csproj
index f1442ca..8b9553d 100644
--- a/SharedCode.DependencyInjection/DependencyInjection.csproj
+++ b/SharedCode.DependencyInjection/DependencyInjection.csproj
@@ -4,7 +4,7 @@
latest
shared code, c#, utilities, dependency injection
SharedCode.DependencyInjection
- netstandard2.0;netstandard2.1;net8.0;net9.0
+ netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0
diff --git a/SharedCode.MediatR/MediatR.csproj b/SharedCode.MediatR/MediatR.csproj
index 02ced03..27bc25e 100644
--- a/SharedCode.MediatR/MediatR.csproj
+++ b/SharedCode.MediatR/MediatR.csproj
@@ -2,7 +2,7 @@
SharedCode.MediatR
SharedCode.MediatR
- net8.0;net9.0
+ net8.0;net9.0;net10.0
diff --git a/SharedCode.Web/Web.csproj b/SharedCode.Web/Web.csproj
index e79b7f5..9787a96 100644
--- a/SharedCode.Web/Web.csproj
+++ b/SharedCode.Web/Web.csproj
@@ -4,7 +4,7 @@
Library
true
SharedCode.Web
- net9.0
+ net9.0;net10.0
diff --git a/SharedCode.Windows.WPF/Windows.WPF.csproj b/SharedCode.Windows.WPF/Windows.WPF.csproj
index 2648712..c8a2b67 100644
--- a/SharedCode.Windows.WPF/Windows.WPF.csproj
+++ b/SharedCode.Windows.WPF/Windows.WPF.csproj
@@ -5,7 +5,7 @@
shared code, c#, utilities, Windows, WPF
SharedCode.Windows.WPF
10.0.19041.0
- net9.0-windows10.0.22621.0
+ net9.0-windows10.0.22621.0;net10.0-windows10.0.22621.0
true