Microsoft.Extensions.DependencyInjection에 대한 시간 범위 등록 메커니즘
8162 단어 dotnetprogramming
Transient
등록은 요청 시 항상 서비스의 새 인스턴스를 생성합니다. Scoped
로 등록되면 범위 내에 단일 인스턴스가 있습니다. 범위는 무엇이든 될 수 있으며 IServiceProvider.CreateScope()
확장 메서드를 통해 생성됩니다. 예를 들어 ASP.NET에서 모든 HTTP 요청에는 자체 범위가 있습니다. 마지막 유형은 Singleton
(GoF 디자인 패턴)이며 이름에서 알 수 있듯이 항상 동일한 인스턴스를 확인합니다.요즘 저는 시간 범위가 지정되는 DI 등록을 원했습니다. 따라서 유효한 시간이 만료되면 새 인스턴스를 반환합니다. 유통기한이라고 생각하시면 됩니다.
참조 시간은 처음 액세스(생성)한 시간이어야 합니다.
서비스 확인이 작동하는 방식과 새로운 인스턴스가 생성되는 경우에 대한 다이어그램
용법
패키지
DavidKroell.TimeScoped
를 프로젝트에 설치합니다. 패키지는 NuGet.org 에서 구할 수 있습니다.AddTimeScoped<TSerice>
를 사용하여 DI 컨테이너에 시간 범위 서비스를 추가할 수 있습니다. 그런 다음 시간 범위 서비스를 일반 인터페이스로 확인할 수 있습니다. ITimeScoped<DummyService>
이 인터페이스에는 실제 서비스가 될 단일 속성(Instance
)이 있습니다.var sc = new ServiceCollection();
sc.AddTimeScoped<DummyService>(TimeSpan.FromSeconds(3));
var provider = sc.BuildServiceProvider();
var timeScopedService = provider.GetRequiredService<ITimeScoped<DummyService>>();
var instance1 = timeScopedService.Instance;
await Task.Delay(5000);
// should return a new instance, because 3 seconds are over
var instance2 = timeScopedService.Instance;
Assert.AreNotSame(instance1, instance2);
Never store an instance of your real service in an variable!
You should always access it within the wrapper class.
구현
이것의 구현은 매우 간단합니다. 기본 논리는 모두
Instance
getter 메서드 내에 있습니다.internal class TimeScopedProvider<TService> : ITimeScoped<TService> where TService : class
{
private readonly IServiceProvider _provider;
private readonly TimeSpan _validTimeSpan;
private DateTime? _validUntil;
private TService? _instance;
public TService Instance => GetInstance();
public TimeScopedProvider(IServiceProvider provider, TimeSpan validTimeSpan)
{
_provider = provider;
_validTimeSpan = validTimeSpan;
}
private TService GetInstance()
{
if (_validUntil == null || _validUntil < DateTime.Now)
{
lock (this)
{
CleanupOldInstance();
_instance = (TService) _provider.GetService(typeof(TService))!;
_validUntil = DateTime.Now.Add(_validTimeSpan);
}
}
return _instance!;
}
private void CleanupOldInstance()
{
if (_instance is IDisposable disposable)
{
disposable.Dispose();
}
_instance = null;
}
}
요약
때때로 새 인스턴스를 원할 때 이 구현을 사용할 수 있지만 모든 액세스에 대해서는 아닙니다. 간단한 캐시 구현을 위해 한 번 사용했습니다.
Reference
이 문제에 관하여(Microsoft.Extensions.DependencyInjection에 대한 시간 범위 등록 메커니즘), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/davidkroell/a-time-scoped-registration-mechanism-for-microsoftextensionsdependencyinjection-29ef텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)