2017-05-24 33 views
0

我目前正在嘗試從溫莎城堡遷移到簡單噴油器。從溫莎遷移到簡單的噴油器,HttpContext.Current.Session爲空

內的服務我在試圖注入HttpSessionStateBase所示下面的構造函數的服務:

public UserSession(IResourceRepository resourceRepository, IUser user, 
    IRoleResolver roleResolver, IApproverRepository approverRepository, 
    IActiveDirectory activeDirectory, HttpSessionStateBase httpSession, 
    Settings appSettings) 
{ 
    _resourceRepository = resourceRepository; 
    _user = user; 
    _roleResolver = roleResolver; 
    _approverRepository = approverRepository; 
    _activeDirectory = activeDirectory; 
    _httpSession = httpSession; 
    _allowedUsernamePostfixes = appSettings.AuthenticationAllowedUsernamePostfixes; 
} 

要與溫莎做到這一點我可以使用一個FactoryMethod注入HttpSessionStateBase作爲新HttpSessionStateWrapper。

private static IWindsorContainer BuildWindsorContainer() 
{ 
    var container = new WindsorContainer(); 
    container.Kernel.Resolver.AddSubResolver(
     new CollectionResolver(container.Kernel, true)); 

    container.Register(
     Component.For<IWindsorContainer>().Instance(container) 
     ); 

    container.Install(FromAssembly.This()); 

    container.Register(
     Component.For<HttpRequestBase>() 
      .UsingFactoryMethod(() => new HttpRequestWrapper(HttpContext.Current.Request)) 
      .LifestyleTransient(), 
     Component.For<HttpSessionStateBase>() 
      .UsingFactoryMethod(() => new HttpSessionStateWrapper(HttpContext.Current.Session)) 
      .LifestyleTransient(), 


    return container; 
} 

該方法在Global.asax.cs文件中的ASP.NET MVC 4項目的Application_Start方法中被調用時將工作。

我現在已經嘗試通過將兩個溫莎FactoryMethods如下簡單的代碼注入到其轉換爲簡單的進樣:

container.Register<HttpRequestBase>(
    () => new HttpRequestWrapper(HttpContext.Current.Request), 
    Lifestyle.Transient); 

container.Register<HttpSessionStateBase>(
    () => new HttpSessionStateWrapper(HttpContext.Current.Session), 
    Lifestyle.Transient); 

的問題是,當我把在Application_Start方法這種方法則的HttpContext。 Simple Inject調用容器驗證方法時,Current.Session將爲null。

任何人都有這個解決方案嗎?

回答

0

問題是,當我在Application_Start方法中調用此方法時,當Simple Inject調用容器驗證方法時,HttpContext.Current.Session將爲null。

與溫莎城堡,你會有同樣的問題,如果它包含像簡單注射器那樣的驗證功能。如果您刪除對container.Verify()的呼叫,您將獲得與Castle Winsdor相同的行爲,即您沒有得到任何驗證。

顯然,這並不理想,這可能是您希望遷移到Simple Injector的原因之一。

這個問題歸結爲使用運行時狀態構建應用程序組件的問題,這是一種代碼異味,如expressed here。所以在一個理想的情況下,你應該減輕這一點,並確保HttpContext.Current不叫做suring object construction,而只是之後的對象構造。

儘管您應該真的努力做到這一點,但我可以理解,這可能是重構應用程序的一項艱鉅任務,並且比僅更改DI容器花費的時間要多得多。不管怎樣,你都應該記住(近)將來的事情。

也就是說,實際的(和時間)解決初始化過程中,以製造假HttpRequestHttpSession對象,如下圖所示:

container.Register<HttpRequestBase>(
    () => HttpContext.Current != null 
     ? new HttpRequestWrapper(HttpContext.Current.Request) 
     : new HttpRequestWrapper(new HttpRequest("", "http://fake", "")), 
    Lifestyle.Scoped); 

container.Register<HttpSessionStateBase>(
    () => HttpContext.Current != null 
     ? new HttpSessionStateWrapper(HttpContext.Current.Session) 
     : (HttpSessionState)typeof(HttpSessionState) 
      .GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic) 
      .First() 
      .Invoke(new object[] { null }), 
    Lifestyle.Scoped); 

這是相當難看,尤其是HttpSessionState創建(有一個內部構造函數),但它保證了其他配置的可驗證性。

+0

嗨,你是正確的代碼與使用運行時數據的氣味。令人遺憾的是,應用程序的創始人基於使用運行時數據的服務進行身份驗證...... 我已經嘗試了一些代碼,但無法使HttpSessionStateBase工作,因爲HttpSessionStateWrapper和HttpSessionState之間沒有隱式類型。 – McBoman

+0

對不起,我沒有時間測試代碼,希望這會給你一些關於如何解決這個問題的指導。 – Steven

+0

當然,感謝您的幫助。 – McBoman