Refactor ReCClient API for async and DI compatibility
Updated `RecActions.InvokeAsync(...).Sync()` to align with migration guidelines, marking `Sync()` as `[Obsolete]` and recommending `async/await` for asynchronous patterns. Enhanced `BuildStaticClient` methods to include an optional `configureOptions` parameter for flexible `ReCClientOptions` configuration. Added conditional compilation for nullable reference type compatibility across .NET Framework and modern .NET versions. Updated `Services.AddRecClient` calls to support `configureOptions`. Retained `[Obsolete]` on static helpers to encourage dependency injection (`services.AddRecClient(...)`) for new code. Revised migration notes to emphasize deprecation of synchronous methods, static helpers, and the importance of adopting modern async and DI patterns. Clarified changes to `GetAsync` methods, error handling with `ReCApiException`, and deserialization behavior.
This commit is contained in:
@@ -431,40 +431,3 @@ Migrations-Tipps:
|
||||
|
||||
* **`BuildStaticClient` / `Create`** ? ersetzen durch `services.AddRecClient(...)` und Konstruktor-Injektion.
|
||||
* **`TaskSyncExtensions.Sync`** ? den umliegenden Codepfad asynchron machen (`async Task`) und `await` verwenden.
|
||||
|
||||
== 7. Migrations-Hinweise (jüngste Änderungen) ==
|
||||
|
||||
Folgende Änderungen sind zu beachten, falls Sie von einer früheren Version migrieren:
|
||||
|
||||
* **GET-Methoden geben jetzt deserialisierte Werte zurück, nicht mehr `HttpResponseMessage`.**
|
||||
** `GetAsync<T>(...)` liest den Body **einmal** und gibt `T?` zurück.
|
||||
** `GetAsync(...)` (ohne Typparameter) gibt `dynamic`/`JsonElement` zurück.
|
||||
** Falls Sie zuvor `HttpResponseMessage` selbst behandelt haben (Status, Body lesen, deserialisieren), entfällt dieser Schritt.
|
||||
* **Einheitliche Fehlerbehandlung über `ReCApiException`.**
|
||||
** Bei HTTP-Fehlern wird konsistent diese Exception geworfen – auch für GET.
|
||||
** Sie müssen nicht mehr selbst auf `IsSuccessStatusCode` prüfen.
|
||||
* **`GetDynamicAsync` wurde umbenannt zu `GetAsync` (Overload).**
|
||||
** Es gibt nun pro API-Klasse zwei `GetAsync`-Overloads: typisiert und dynamisch. Aufrufe von `GetDynamicAsync(...)` müssen zu `GetAsync(...)` geändert werden.
|
||||
* **`TaskSyncExtensions` und statische `ReCClient`-Helfer sind `[Obsolete]`.**
|
||||
|
||||
== 8. FAQ ==
|
||||
|
||||
**Warum gibt `GetAsync<T>` einen deserialisierten Wert statt `HttpResponseMessage` zurück?**
|
||||
|
||||
Damit wird der Response-Body genau einmal gelesen, Fehler werden einheitlich über `ReCApiException` behandelt, und Aufrufer müssen weder selbst auf den Statuscode prüfen noch die Antwort manuell deserialisieren.
|
||||
|
||||
**Wozu der nicht-generische `GetAsync(...)`-Overload?**
|
||||
|
||||
Er ist ein Komfort-Aufruf für Fälle, in denen Sie das Schema nicht (oder noch nicht) typisieren möchten. Intern ruft er `GetAsync<object>` auf und liefert ein `JsonElement` zurück, das Sie ad hoc inspizieren können.
|
||||
|
||||
**Gibt es einen Konflikt zwischen dem generischen und dem nicht-generischen `GetAsync`?**
|
||||
|
||||
Nein. Beide Methoden haben unterschiedliche Signaturen (ein Methodengeneric-Parameter ist Teil der Signatur). Der Compiler wählt anhand der Aufrufsyntax (`GetAsync<T>(...)` vs. `GetAsync(...)`).
|
||||
|
||||
**Soll ich die statischen `ReCClient.Create`-Helfer noch verwenden?**
|
||||
|
||||
Nur in Legacy-Szenarien. Für neuen Code: DI mit `services.AddRecClient(...)`.
|
||||
|
||||
**Sind synchrone Aufrufe via `Sync()` sicher?**
|
||||
|
||||
Nicht generell. In Umgebungen mit `SynchronizationContext` riskieren sie Deadlocks. Verwenden Sie `async/await`.
|
||||
|
||||
@@ -93,14 +93,19 @@ namespace ReC.Client
|
||||
/// This method should only be called once during application startup.
|
||||
/// </remarks>
|
||||
/// <param name="apiUri">The base URI of the ReC API.</param>
|
||||
/// <param name="configureOptions">An optional callback to configure <see cref="ReCClientOptions"/>.</param>
|
||||
/// <exception cref="InvalidOperationException">Thrown if the static provider has already been built.</exception>
|
||||
[Obsolete("Use a local service collection instead of the static provider.")]
|
||||
public static void BuildStaticClient(string apiUri)
|
||||
#if NETFRAMEWORK
|
||||
public static void BuildStaticClient(string apiUri, Action<ReCClientOptions> configureOptions = null)
|
||||
#else
|
||||
public static void BuildStaticClient(string apiUri, Action<ReCClientOptions>? configureOptions = null)
|
||||
#endif
|
||||
{
|
||||
if(Provider != null)
|
||||
throw new InvalidOperationException("Static Provider is already built.");
|
||||
|
||||
Services.AddRecClient(apiUri);
|
||||
Services.AddRecClient(apiUri, configureOptions);
|
||||
Provider = Services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
@@ -111,14 +116,19 @@ namespace ReC.Client
|
||||
/// This method should only be called once during application startup.
|
||||
/// </remarks>
|
||||
/// <param name="configureClient">An action to configure the <see cref="HttpClient"/>.</param>
|
||||
/// <param name="configureOptions">An optional callback to configure <see cref="ReCClientOptions"/>.</param>
|
||||
/// <exception cref="InvalidOperationException">Thrown if the static provider has already been built.</exception>
|
||||
[Obsolete("Use a local service collection instead of the static provider.")]
|
||||
public static void BuildStaticClient(Action<HttpClient> configureClient)
|
||||
#if NETFRAMEWORK
|
||||
public static void BuildStaticClient(Action<HttpClient> configureClient, Action<ReCClientOptions> configureOptions = null)
|
||||
#else
|
||||
public static void BuildStaticClient(Action<HttpClient> configureClient, Action<ReCClientOptions>? configureOptions = null)
|
||||
#endif
|
||||
{
|
||||
if (Provider != null)
|
||||
throw new InvalidOperationException("Static Provider is already built.");
|
||||
|
||||
Services.AddRecClient(configureClient);
|
||||
Services.AddRecClient(configureClient, configureOptions);
|
||||
Provider = Services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user