Created
November 10, 2020 21:46
-
-
Save JimBobSquarePants/d5ea04fb5f2eed9950b228f51a588799 to your computer and use it in GitHub Desktop.
Allows the controlled running of scoped services with automatic cleanup.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading.Tasks; | |
using Microsoft.Extensions.DependencyInjection; | |
namespace ThingsWhatImNotProudOf | |
{ | |
/// <summary> | |
/// Allows the manufacture and running of items within a smaller lifetime scope than the parent. | |
/// To be used sparingly when unable to inject a service within the required scope. | |
/// </summary> | |
public sealed class ScopedServiceRunner | |
{ | |
private readonly IServiceScopeFactory serviceScopeFactory; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="ScopedServiceRunner"/> class. | |
/// </summary> | |
/// <param name="serviceScopeFactory">The scope factory.</param> | |
public ScopedServiceRunner(IServiceScopeFactory serviceScopeFactory) | |
=> this.serviceScopeFactory = serviceScopeFactory; | |
/// <summary> | |
/// Runs the given <see cref="Action{T}"/> in the current scope. | |
/// </summary> | |
/// <typeparam name="T">The type of object to invoke and run against.</typeparam> | |
/// <param name="command">The command to run.</param> | |
public void RunScoped<T>(Action<T> command) | |
{ | |
using (IServiceScope scope = this.serviceScopeFactory.CreateScope()) | |
{ | |
// Scope disposes of all disposables. | |
command(scope.ServiceProvider.GetRequiredService<T>()); | |
} | |
} | |
/// <summary> | |
/// Runs the given <see cref="Func{T, TResult}"/> in the current scope. | |
/// </summary> | |
/// <typeparam name="T">The type of object to invoke and run against.</typeparam> | |
/// <typeparam name="TResult">The type of result.</typeparam> | |
/// <param name="command">The command to run.</param> | |
/// <returns>The <typeparamref name="TResult"/>.</returns> | |
public TResult RunScoped<T, TResult>(Func<T, TResult> command) | |
{ | |
using (IServiceScope scope = this.serviceScopeFactory.CreateScope()) | |
{ | |
// Scope disposes of all disposables. | |
return command(scope.ServiceProvider.GetRequiredService<T>()); | |
} | |
} | |
/// <summary> | |
/// Runs the given <see cref="Func{T, TResult}"/> in the current scope. | |
/// </summary> | |
/// <typeparam name="T">The type of object to invoke and run against.</typeparam> | |
/// <typeparam name="TResult">The type of result.</typeparam> | |
/// <param name="command">The command to run.</param> | |
/// <returns>The <typeparamref name="TResult"/>.</returns> | |
public async Task<TResult> RunScopedAsync<T, TResult>(Func<T, Task<TResult>> command) | |
{ | |
using (IServiceScope scope = this.serviceScopeFactory.CreateScope()) | |
{ | |
// Scope disposes of all disposables. | |
return await command(scope.ServiceProvider.GetRequiredService<T>()); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment