programing

Unity의 통화당 싱글톤 컨텍스트(웹 요청)

subpage 2023. 8. 2. 09:05
반응형

Unity의 통화당 싱글톤 컨텍스트(웹 요청)

며칠 전에 ASP에 문제가 있었습니다.네트 스레딩.저는 웹 요청별로 싱글톤 오브젝트를 갖고 싶었습니다.저는 사실 이것이 제 작업 단위에 필요합니다.저는 아이덴티티 맵이 요청 전반에 걸쳐 유효하도록 웹 요청당 작업 단위를 인스턴스화하고 싶었습니다.이러한 방식으로 IoC를 사용하여 저장소 클래스에 자신의 IUNitOfWork를 투명하게 주입하고 동일한 인스턴스를 사용하여 엔티티를 쿼리한 다음 업데이트할 수 있습니다.

유니티를 사용하고 있기 때문에 실수로 PerThreadLife를 사용했습니다.시간 관리자.저는 곧 ASP를 깨달았습니다.Net Threading 모델이 원하는 것을 지원하지 않습니다.기본적으로 스레드 풀을 사용하고 스레드를 재활용합니다. 즉, 스레드당 하나의 UnitOfWork!!하지만 제가 원했던 것은 웹 요청당 한 단위의 작업이었습니다.

약간의 구글링이 에게 이 훌륭한 게시물을 주었습니다.그것이 바로 제가 원했던 것이었습니다. 꽤 쉽게 달성할 수 있는 통일성 부분을 제외하고 말입니다.

이것은 PerCallContextLife에 대한 나의 구현입니다.단일화를 위한 TimeManager:

public class PerCallContextLifeTimeManager : LifetimeManager
{
    private const string Key = "SingletonPerCallContext";

    public override object GetValue()
    {
        return CallContext.GetData(Key);
    }

    public override void SetValue(object newValue)
    {
        CallContext.SetData(Key, newValue);
    }

    public override void RemoveValue()
    {
    }
}

그리고 물론 이것을 사용하여 다음과 유사한 코드로 작업 단위를 등록합니다.

unityContainer
            .RegisterType<IUnitOfWork, MyDataContext>(
            new PerCallContextLifeTimeManager(),
            new InjectionConstructor());

누군가에게 시간을 좀 절약해 주기를 바랍니다.

완벽한 솔루션이지만 LifetimeManager의 각 인스턴스는 상수가 아닌 고유한 키를 사용해야 합니다.

private string _key = string.Format("PerCallContextLifeTimeManager_{0}", Guid.NewGuid());

그렇지 않은 경우 PerCallContextLife에 둘 이상의 개체가 등록되어 있습니다.TimeManager는 CallContext에 액세스하기 위해 동일한 키를 공유하고 있으므로 원하는 개체를 다시 찾을 수 없습니다.

또한 RemoveValue를 구현하여 개체를 정리할 가치가 있습니다.

public override void RemoveValue()
{
     CallContext.FreeNamedDataSlot(_key);
}

이를 PerCallContextLife라고 부르는 것은 괜찮지만,TimeManager, ASP로 간주되는 은 "안전하지 않다"고 확신합니다.요청별 NetLifeTimeManager입니다.

ASP.Net이 스레드 스왑을 수행할 경우 CallContext를 통해 새 스레드로 전달되는 유일한 항목은 현재 HttpContext이며, CallContext에 저장된 다른 항목은 모두 사라집니다.이것은 위의 코드가 과부하 상태에서 의도하지 않은 결과를 초래할 수 있다는 것을 의미합니다. 그리고 저는 그 이유를 추적하는 것이 정말 고통스러울 것이라고 생각합니다!

이를 "안전한" 유일한 방법은 HttpContext입니다.현재의.항목 또는 다음과 같은 작업 수행:

public class PerCallContextOrRequestLifeTimeManager : LifetimeManager
{
    private string _key = string.Format("PerCallContextOrRequestLifeTimeManager_{0}", Guid.NewGuid());

    public override object GetValue()
    {
      if(HttpContext.Current != null)
        return GetFromHttpContext();
      else
        return GetFromCallContext();
    }

    public override void SetValue(object newValue)
    {
      if(HttpContext.Current != null)
        return SetInHttpContext();
      else
        return SetInCallContext();
    }

    public override void RemoveValue()
    {
    }
}

이것은 분명히 시스템에 의존한다는 것을 의미합니다.웹 :-(

이에 대한 자세한 내용은 다음 사이트에서 확인할 수 있습니다.

http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html

당신의 기여에 감사드립니다.

그러나 구현을 제안하는 질문에는 두 가지 단점이 있습니다. 그 하나는 이미 답변에서 Steven Robbins와 Micah Zoltu가 코멘트에서 언급한 심각한 버그입니다.

  1. 통화 컨텍스트가 Asp에 의해 보존되는 것을 보장하지 않습니다.단일 요청에 대한 순입니다.부하가 걸리면 다른 것으로 전환하여 제안된 구현이 중단될 수 있습니다.
  2. 요청 종료 시 종속성 해제는 처리하지 않습니다.

지금 유니티.Mvc Nuget 패키지는 작업을 위해 a를 제공합니다.관련 항목을 등록하는 것을 잊지 마십시오.UnityPerRequestHttpModule부트스트랩 코드에서 그렇지 않으면 종속성 해제도 처리되지 않습니다.

부트스트래핑 사용

DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));

web "web.config"에 .system.webServer/modules

<add name="UnityPerRequestHttpModule" type="Microsoft.Practices.Unity.Mvc.UnityPerRequestHttpModule, Microsoft.Practices.Unity.Mvc" preCondition="managedHandler" />

현재의 구현은 웹 양식에도 적합한 것으로 보입니다.그리고 MVC에 의존하지도 않습니다.불행하게도, 그것의 어셈블리는 그것이 포함하는 다른 클래스들 때문에 그렇게 합니다.

종속성을 사용자 수 EndRequest모듈 실행 순서에 따라 다릅니다.

언급URL : https://stackoverflow.com/questions/1151201/singleton-per-call-context-web-request-in-unity

반응형