Cleanup and async helpers
Cleanup.SafeMethod
Pineapple.Common.Cleanup.SafeMethod runs an action and swallows any exception, returning a fluent object for follow-up actions. Use it in finally blocks and Dispose methods where a secondary failure must not mask the original one.
using static Pineapple.Common.Cleanup;
SafeMethod(() => File.Delete(tempPath))
.OnSuccess(() => _logger.LogDebug("Temp file removed"))
.OnFailure(() => _logger.LogWarning("Could not remove {Path}", tempPath))
.Continue(connection.Close);
| Method | Runs when |
|---|---|
OnSuccess(action) |
The previous action succeeded |
OnFailure(action) |
The previous action threw |
Continue(action) |
Always |
Every follow-up is itself run safely.
SynchronizationContextScope
Temporarily replaces SynchronizationContext.Current, restoring the original on dispose. SuppressSynchronizationContextScope sets it to null.
using Pineapple.Threading;
using (new SuppressSynchronizationContextScope())
{
// Continuations run on the thread pool, not the captured UI/request context.
var result = LoadAsync().GetAwaiter().GetResult();
}
Pair with Preconditions.CheckIsNotOnSynchronizationContext() to assert that code runs without a context.
Immutable collection helpers
Pineapple.Extensions.ImmutableExtensions adds null-tolerant Append methods to IImmutableList<T> and IImmutableDictionary<TKey, TValue>:
IImmutableList<Order> list = null;
list = list.Append(order); // creates the list if null
list = list.Append(moreOrders);
Dependency injection helpers
Pineapple.Extensions.ServiceCollectionExtensions adds services.IsConfigured<T>() (is a service of type T registered?) and services.Configure<T>() (register T as a singleton).
Questions about async helpers
How do I avoid deadlocks when blocking on async code in .NET?
Prefer async all the way. When you must block (for example in a legacy UI or ASP.NET handler), clear the SynchronizationContext first so continuations don’t try to resume on the blocked thread: using (new SuppressSynchronizationContextScope()) { task.GetAwaiter().GetResult(); }.