Skip to content

Instantly share code, notes, and snippets.

@GeeWee
Created September 3, 2021 08:35
Show Gist options
  • Save GeeWee/97b29e21a8dea7e88ec0792ab76d335d to your computer and use it in GitHub Desktop.
Save GeeWee/97b29e21a8dea7e88ec0792ab76d335d to your computer and use it in GitHub Desktop.
using System;
using Microsoft.Extensions.DependencyInjection;
namespace Scopes
{
/// <summary>
/// This allows access to a Scoped or transient service outside of a scope. It returns a scope and a service.
/// The scope must be disposed of, after you're done with the service
/// </summary>
/// <typeparam name="T">The type of the service</typeparam>
public interface IScopedServiceProvider<T> where T : class
{
DisposableScope<T> GetScopedService();
}
public sealed class ScopedServiceProvider<T> : IScopedServiceProvider<T> where T : class
{
private readonly IServiceScopeFactory _scopeFactory;
public ScopedServiceProvider(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public DisposableScope<T> GetScopedService()
{
var scope = _scopeFactory.CreateScope();
var requestedService = scope.ServiceProvider.GetRequiredService<T>();
return new DisposableScope<T>(scope, requestedService);
}
}
/// <summary>
/// Disposable wrapper around a IServiceScope, where you can access a scoped service
/// before you dispose it
/// </summary>
/// <typeparam name="T">The type of service provided by the scope</typeparam>
public class DisposableScope<T> : IDisposable
where T : class
{
private readonly IServiceScope _scope;
public T Service { get; }
public DisposableScope(IServiceScope scope, T service)
{
this._scope = scope;
Service = service;
}
public void Dispose()
{
_scope.Dispose();
}
}
}
public class PeriodicBackgroundService : BackgroundService
{
private IScopedServiceProvider<SomeService> _serviceProvider;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
using var scope = _serviceProvider.GetScopedService();
var service = scope.Service;
service.DoStuff();
}
catch (Exception e)
{
Console.WriteLine(e);
}
await Task.Delay(1000, stoppingToken);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment