문제

ASP.NET MVC 및 StructureMap IOC/Di로 작은 웹 상점을 짓고 있습니다. 내 바스켓 클래스는 지속성을 위해 세션 객체를 사용하고 SM을 사용하여 iBasket 인터페이스를 통해 바구니 객체를 만들고 싶습니다. 바구니 구현에는 생성자에서 HTTPSESSIONSTATEBASE (MVC의 세션 상태 래퍼)가 필요하며 컨트롤러/작업 내부에서 사용할 수 있습니다. SM에 대한 IBASKET 구현을 어떻게 등록합니까?
이것은 내 바스켓 인터페이스입니다.

public interface IBasketService    {
    BasketContent GetBasket();
    void AddItem(Product productItem);
    void RemoveItem(Guid guid);
}

SM 등록 :

ForRequestedType(typeof (IBasketService)).TheDefaultIsConcreteType(typeof (StoreBasketService));

그러나 내 StoreBasketService 구현은 생성자가 있습니다.

public StoreBasketService(HttpSessionStateBase sessionState)

컨트롤러에서만 사용할 수있는 SM에 httpsessionstatebase 객체를 어떻게 제공합니까?
이것은 SM IOC/DI의 첫 번째 사용이며 공식 문서 및 웹 사이트에서 솔루션/예를 찾을 수 없습니다.)

도움이 되었습니까?

해결책

STOREBASKETSERVICE가 세션을 사용해야하는 경우 httpsessionStatebase를 사용하는 대신 httpsessionState 주변의 인터페이스와 래퍼를 정의하여 structuremap에도 등록 할 수 있도록 유혹을받습니다. 문맥. 래퍼를 StructureMap으로 등록한 다음 StoreBasketService가 생성자에 대한 인수로 인터페이스를 가져 가도록하십시오. 그런 다음 구조 맵은 인터페이스 래퍼의 인스턴스를 작성하여 StoreBasketService 클래스에 주입하는 방법을 알아야합니다.

인터페이스와 래퍼를 사용하면 장치 테스트에서 래퍼를 조롱 할 수 있습니다. httpsessionstatebase는 실제 세션을 조롱 할 수있는 방식과 같은 방식으로 muc입니다.

public interface IHttpSessionStateWrapper
{
    HttpSessionState GetSessionState();
}

public class HttpSessionStateWrapper : IHttpSessionStateWrapper
{
    public virtual HttpSessionState GetSessionState()
    {
       return HttpContext.Current.Session;
    }
}

ForRquestedType(typeof(IHttpSessionStateWrapper))
   .TheDefaultIsConcreteType(typeof(IHttpSessionStateWrapper));

public class StoreBasketService
{
   HttpSessionState session;
   public StoreBasketService( IHttpSessionstateWrapper wrapper )
   {
      session = wrapper.GetSessionState();
   }

   // basket implementation ...
}

그러나 구조 맵이 실제로 세션에 바구니를 저장할 수 있습니다. .CacheBy(InstanceScope.HttpContext) 등록 할 때. StoreBasketService가 세션에 물건을 저장하는 대신 내부 스토리지를 구현하는 것이 실제로 더 나을 수 있습니다. 그러면 세션 상태에 대한 의존성을 완전히 (클래스의 관점에서 볼 때) 솔루션이 더 간단 할 수 있습니다. 내부 스토리지는 다음과 같습니다 Dictionary<Guid,Product> 인터페이스를 통해 액세스하는 방법이므로.

또한보십시오:

http://www.lostechies.com/blogs/chad_myers/archive/2008/07/15/structuremap-basic-scenario-usage.aspx

http://www.lostechies.com/blogs/chad_myers/archive/2008/07/17/structuremap-medium-20-usage-scenarios.aspx

다른 팁

ForRequestedType<IBasketService>()
    .TheDefault.Is.OfConcreteType<StoreBasketService>()
    .WithCtorArg("sessionState").EqualTo(HttpContext.Current.Session);

?? 그게 작동합니까?

방금 structuremap으로 시작했고 당신이 설명하는 결과를 얻지 못합니다. 간단한 클래스를 사용하여 간단한 테스트를 수행하여 Cacheby httpcontext에 대한 structuremap을 구성하고 내가 볼 수있는 내용에서 Cacheby.httpcontext는 동일한 요청 내에서 동일한 인스턴스를 얻는다는 것을 의미합니다.

내 클래스의 생성자는 개인 필드에서 날짜/시간을 설정합니다. 1 초 간격으로 MyClass의 2 인스턴스를 가져 오는 버튼이 있습니다 ... 그런 다음 두 인스턴스의 시간을 레이블에 표시합니다.

이 버튼을 처음 누르면 객체 A와 B는 생성 시간이 예상과 정확히 동일하기 때문에 동일한 인스턴스입니다.

버튼을 두 번째로 클릭하면 인스턴스가 세션에 캐시되면 생성 시간이 변경되지 않을 것으로 예상됩니다 ... 그러나 내 테스트에서는 새로운 생성 시간이 있습니다 ...

structureMap 구성 :

         ObjectFactory.Initialize(x=>x.ForRequestedType<MyClass>(). CacheBy(InstanceScope.HttpContext));

버튼 테스트 페이지의 이벤트를 클릭했습니다

     protected void btnTest_Click(object sender, EventArgs e)
    {
        MyClass c = ObjectFactory.GetInstance<MyClass>();
        System.Threading.Thread.Sleep(1000);
        MyClass b = ObjectFactory.GetInstance<MyClass>();



        lblResult.Text = String.Format("cache by httpcontext First:{0}  Second:{1}  session id {2} ", c.GetTimeCreated(), b.GetTimeCreated(),Session.SessionID);
    }

내 수업

public class MyClass
{
    private DateTime _timeCreated;
    public MyClass()
    {
        _timeCreated = DateTime.Now;
    }

    public string GetTimeCreated()
    {
        return _timeCreated.ToString("dd/MM/yyyy hh:mm:ss");
    }
}

ObjectFactory.inject 메소드 중 하나를 사용하여 httpsessionStateBase를 StructureMap에 주입 할 수도 있습니다. 그런 다음 주입 된 httpsessionstatebase로 생성자를 호출합니다.

방금 사용자 정의 범위를 만들기 위해 처음 시도했습니다. 작은 웹 애플리케이션을 구축하고 볼 수있는 한 작동하는 것 같습니다. 이것은 현재 사용자 세션 내부의 객체를 캐시하고 같은 세션 내부에 남아있는 한 동일한 객체를 반환합니다.

public class HttpSessionBuilder : CacheInterceptor
{
    private readonly string _prefix = Guid.NewGuid().ToString();

    protected override CacheInterceptor clone()
    {
        return this;
    }

    private string getKey(string instanceKey, Type pluginType)
    {
        return string.Format("{0}:{1}:{2}", pluginType.AssemblyQualifiedName, instanceKey, this._prefix);
    }

    public static bool HasContext()
    {
        return (HttpContext.Current.Session != null);
    }

    protected override bool isCached(string instanceKey, Type pluginType)
    {
        return HttpContext.Current.Session[this.getKey(instanceKey, pluginType)] != null;
    }

    protected override object retrieveFromCache(string instanceKey, Type pluginType)
    {
        return HttpContext.Current.Session[this.getKey(instanceKey, pluginType)];
    }

    protected override void storeInCache(string instanceKey, Type pluginType, object instance)
    {
        HttpContext.Current.Session.Add(this.getKey(instanceKey, pluginType), instance);
    }

}

Global.asax Application_start의 다음과 같이 ObjectFactory를 구성해야합니다.

        ObjectFactory.Initialize(x=>
            x.ForRequestedType<MyClass>().InterceptConstructionWith(new HttpSessionBuilder()));
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top