DisposableDbObject
(IDisposable
구현) 타사 개체를 사용하는 MyService
클래스가 포함 된 라이브러리를 만듭니다. Autofac ContainerBuilder
확장을 하나의 인스턴스로 등록합니다 (객체 생성에는 비용이 많이 듭니다). 문제는 한 번에 DisposableDbObject
인스턴스를 새로 고쳐야한다는 것입니다 (파일에서 새 버전의 데이터베이스를로드해야하는 일부 메모리 내장 DB의 래퍼입니다). 내가 아는 한, SingletonInstance
(그리고 ContainerBuilder.Update
은 더 이상 사용되지 않음) 구성 요소의 참조를 대체하는 안전한 방법이 없으므로 DisposableDbObject
을 DisposableDbObjectProvider
클래스로 감싸서 싱글 톤으로 등록하고 자유롭게 손을 대면서 밑에있다. 그래서 제 설정은 이렇게됩니다.Autofac에서 싱글 톤으로 등록 된 일회용 개체 교체
// DisposableDbObjectProvider.cs
public interface IDisposableDbObjectProvider
{
DisposableDbObject GetDb();
}
public class DisposableDbObjectProvider : IDisposableDbObjectProvider
{
private DisposableDbObject _obj;
public DisposableDbObjectProvider()
{
_obj = new DisposableDbObject("D:\\path\to\file");
}
public DisposableDbObject GetDb()
{
return _obj;
}
public void UpdateDb()
{
_obj = new DisposableDbObject("D:\\path\to\new\file");
}
}
// MyService.cs
interface IMyService
{
string GetStuffFromDb();
}
class MyService
{
private DisposableDbObjectProvider _provider;
class MyService(IDisposableDbObjectProvider provider)
{
_provider = provider;
}
public string GetStuffFromDb()
{
return _provider.GetDb().Read(...);
}
}
// AutofacExtensions.cs
static class AutofacExtensions
{
public static ContainerBuilder WithMyService(this ContainerBuilder builder)
{
builder.RegisterType<DisposableDbObjectProvider >().As<IDisposableDbObjectProvider>().SingleInstance();
builder.RegisterType<MyService>().As<IMyService>();
}
}
이제는이 설정에 3 가지 문제가 있습니다.
(ASP.NET WebApi2 같은) 다중 스레드 클라이언트 앱
MyService
하나 하나 개 개의 스레드 레지스터 (BE 그것을 ASP.NET 의뢰처) 스레드는 상태 업데이트가 수행 된 경우에 개체의 두 가지 버전을 액세스 할 실행 (내 구체적인 경우에 이것은 충분히 좋을지도 모릅니다. 그러나이를 피하고 싶습니다.)DisposableDbObject
참조를 바꾸면 이전에는Dispose
이 필요합니다. 이제 해당 개체에 대한 참조를 유지하는 N> = 1 스레드가있을 수 있으며Dispose
을DisposableDbObjectProvider
에 호출하는 동안 해당 스레드는ObjectDisposedException
으로 끝날 수 있습니다.클라이언트가 사용하는 개체를 폐기해야하는 규칙을 위반합니다. 나는 생각했다
한 가지 방법은 IsAlive
를 통해 (static
필드로하고 WeakReference
추적 목록으로 이전 참조 저장 각 업데이트에 DisposableDbObject
으로 과도 수집 쓰레기입니다 참조를 위해 그것을 스캔 DisposableDbObjectProvider
의 등록을 변경하는 것입니다 DisposableDbObjectProvider.Dispose
가 beha 않을 경우 속성) 아래
public class DisposableDbObjectProvider : IDisposableDbObjectProvider, IDisposable
{
private static DisposableDbObject _obj = new DisposableDbObject("D:\\path\to\file");
private static List<WeakReference> _oldRefs;
public DisposableDbObject GetDb()
{
return _obj;
}
public void UpdateDb()
{
_oldRefs.Add(_obj);
_obj = new DisposableDbObject("D:\\path\to\new\file");
}
public void Dispose()
{
var deadRefs = _oldRefs.Where(x => !x.IsAlive);
oldRefs = oldRefs.Exclude(deadRefs);
foreach(var deadRef in deadRefs)
{
((IDisposable) deadRef.Target).Dispose();
}
}
}
처럼, 이들에 Dispose
를 호출하지만 여전히 나는이 soultion에 대해 매우 안심하지 않습니다 더이 그 바로 해결할 수있는 문제는 (말할 수 없다 여러 스레드가 동시에 호출하는 동안
이러한 문제를 극복하는 가장 좋은 방법은 무엇입니까? 물론 싱글 톤 등록 문제를 우회하는 나의 해결책에 결함이있을 수 있습니다. 더 좋은 접근법이 있다면 그것에 대해 듣고 싶습니다.
DisposableDbObject를 새로 고치는시기는 프로그램에서 어떻게 결정합니까? 패턴이 있으면 싱글 톤으로 등록을 중지하고 올바른 수의 인스턴스를 전달할 수 있습니다. –
'DisposableDbObject'의 소스 코드를 보여주십시오. _ 그렇지 않으면 명확하지 않은 기회가 생길 수도 있습니다 ._ – mjwills