2017-05-24 2 views
0

現在Castle WindsorからSimple Injectorに移行しようとしています。サービス内ウィンザーからシンプルインジェクターへの移行、HttpContext.Current.Sessionがnull

私はサービスのためにコンストラクタの下に示すように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; 
} 

ウィンザーでこれを行うには、私は新しいHttpSessionStateWrapperとしてHttpSessionStateBaseを注入するFactoryMethodを使用することができます。

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メソッドで呼び出されたときに動作します。

私は今、シンプルジェクトコード以下のように2つのウィンザーFactoryMethodsを配置することにより、簡単な注入するためにそれを変換しようとしています:

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

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

問題は、私はのHttpContextその後、Application_Startメソッドでこのメソッドを呼び出すときということです。シンプルインジェクションがコンテナ検証メソッドを呼び出すとき、Current.Sessionはnullになります。

どれでも解決方法はありますか?

答えて

0

問題は、Application_Startメソッドでこのメソッドを呼び出すと、Simple Injectがコンテナのverifyメソッドを呼び出すときにHttpContext.Current.Sessionがnullになることです。

Castle Windsorを使用すると、Simple Injectorのような確認機能が含まれていると同じ問題が発生していました。 container.Verify()への呼び出しを削除すると、Castle Winsdorと同じ動作になります。つまり、確認ができません。

明らかに、これは理想的ではなく、これがSimple Injectorに移行する理由の1つかもしれません。

ランタイム状態を使用してアプリケーションコンポーネントを構築する際の問題点は、expressed hereというコードの匂いです。したがって、理想的な状況では、これを軽減して、HttpContext.Currentがオブジェクトの構築を呼び出すのではなく、オブジェクトの構築後にのみ行うようにしてください。

これを行うには本当に努力する必要がありますが、これはアプリケーションをリファクタリングするためのかなりの手掛かりであり、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

こんにちは、あなたはそのコードがランタイムデータを使用して臭いを覚えています。悲しいことに、アプリケーションの創始者にランタイムデータを使用しているサービスの周りの認証に基づいて... 私はいくつかのコードを試しましたが、HttpSessionStateWrapperとHttpSessionStateの間に暗黙の型がないため、HttpSessionStateBaseを動作させることができません。 – McBoman

+0

申し訳ありませんが、私はコードをテストする時間がありませんでした。うまくいけば、これはあなたにこれを回避する方法のいくつかの指針を与えるでしょう。 – Steven

+0

もちろん、助けてくれてありがとう。 – McBoman

関連する問題