5

WebアプリケーションでAutoFacを使用したい。ルートコンテナ、セッションごとの子コンテナ、リクエストごとの子コンテナがあります。私は、これらのライフタイムスコープを管理するための最良の方法を理解しようとしています。Global.asax.csに、以下を追加しました。

protected void Application_Start(object sender, EventArgs e)
{
    var container = ...;
}

protected void Session_Start(object sender, EventArgs e)
{
    var sessionScope = container.BeginLifetimeScope("session");

    Session["Autofac_LifetimeScope"] = sessionScope;
}

protected void Application_BeginRequest(object sender, EventArgs e)
{
    var sessionScope = (ILifetimeScope) Session["Autofac_LifetimeScope"];
    var requestScope = sessionScope.BeginLifetimeScope("httpRequest");

    HttpContext.Current.Items["Autofac_LifetimeScope"] = requestScope;
}

protected void Application_EndRequest(object sender, EventArgs e)
{
    var requestScope = (ILifetimeScope)HttpContext.Current.Items["Autofac_LifetimeScope"];
    requestScope.Dispose();
}

protected void Session_End(object sender, EventArgs e)
{
    var sessionScope = (ILifetimeScope)Session["Autofac_LifetimeScope"];

    sessionScope.Dispose();
}

protected void Application_End(object sender, EventArgs e)
{
    container.Dispose();
}
  1. 依存関係を取得するための開始点としてrequestScopeを使用するようにAutoFacに指示して、InstancePerLifetimeScopeとして登録した実装がrequestScopeを使用して解決されるようにするにはどうすればよいですか?

  2. それが不可能な場合、AutoFacにsessionScopeからリクエストごとのライフタイムスコープを作成させることはできますか?

  3. それとも私はここで間違った方向に進んでいますか?AutoFacにこの階層を認識させる他の方法はありますか?

ヘルプやその他のコメントをいただければ幸いです。


スティーブンに応えて。

私はまだプロトタイピングの初期段階にありますが、sessionScopeで可能なことは次のとおりです。

  • UserPreferences
  • 認証と承認のコンテキスト(ユーザーIDとロールなど)

作成するアプリケーションとは関係ありませんが、eコマース環境では、ショッピングカートをセッションスコープにすることができます。これはおそらく最良の具体例です。これは、リクエストよりも長持ちしますが、アプリケーションよりも短命であると期待するものです。

これ以上の可能性がありますが、UserPreferences、Authentication、Authorizationの戦略がある場合、その戦略は後で作成される他のコンポーネントにも適用できます。

考えられる代替手段は、要求の開始時に必要なすべての情報を取得し、これらの構成済みコンポーネントを要求スコープに配置することです。期待する結果が得られますが、アプリケーション->セッション->リクエストの階層について考えているモデルとは一致しません。私はそれを維持しようとしている人ではないので、意味のあるシステムを作りたいと思っています。

4

1 に答える 1

13

あなたがする必要があるのはあなた自身を実装することですAutofac.Integration.Mvc.ILifetimeScopeProvider。このインターフェイスは、リクエストの有効期間スコープが生成される方法/場所を管理するものです。デフォルトの1はAutofac.Integration.Mvc.RequestLifetimeScopeProvider、要求ごとにライフタイムスコープの作成、破棄、および保守を処理します。

RequestLifetimeScopeProviderここでコードを参照できます。これを実行する予定がある場合は、これを実行することを強くお勧めします。これは、これらのうちの1つの責任を示す作業コードを含むと私が考えることができる最高のサンプルです。

の実装はILifetimeScopeProvider、セッションの子コンテナを取得し、そこからリクエストコンテナを生成し、リクエストの最後にリクエストコンテナをクリーンアップする場所になります。セッションコンテナが存在しない場合は、そこに作成することもできます。ここでは、セッションコンテナのクリーンアップ/破棄の処理が難しい場合がありますが、設計の観点からは、プロバイダーやアプリケーションクラスではなく、すべてが1か所にあると便利です。

取得したらILifetimeScopeProvider、依存関係リゾルバーを設定するときに使用します。

var scopeProvider = new MyCustomLifetimeScopeProvider(container, configAction);
var resolver = new AutofacDependencyResolver(container, scopeProvider);
DependencyResolver.SetResolver(resolver);

セッションレベルのスコープの概念に関する警告のいくつかの言葉:

  1. あなたのメモリフットプリントは巨大になる可能性があります。最終的には、システム上のすべてのユーザーのライフタイムスコープになります。リクエストの有効期間がポップアップしてすぐに消えますが、これらのセッションレベルのスコープは潜在的に長期間存続します。セッションスコープのアイテムがたくさんある場合は、ユーザーごとにかなり適切なサイズのメモリ使用量があります。人々が適切にログアウトせずにセッションを「放棄」した場合、それはこれらのものが長く存続することです。
  2. ライフタイムスコープとその内容はシリアル化できませんLifetimeScopeのコードを見ると、マークされていません[Serializable]...マークされていたとしても、そこに存在する解決されたオブジェクトは、必ずしもすべてがシリアル化可能とマークされているわけではありません。これは、セッションレベルのライフタイムスコープがメモリ内セッションを備えた単一のボックスで機能する可能性があることを意味するため重要ですが、SQLセッションまたはセッションサービスを備えたファームにデプロイすると、セッションをシリアル化できないため、状況が崩壊します。保存されたスコープ。スコープをシリアル化しないことを選択した場合、マシン間でユーザーごとに異なるスコープがあります。これも潜在的な問題です。
  3. セッションは常に水分補給されるとは限りません。アクセスされているハンドラー(Webフォームなど)がIRequiresSessionStateを実装していない場合、セッションは(処理中かどうかに関係なく)再水和されません。WebフォームとMvcHandlerはデフォルトでそれを実装しているため、問題は発生しませんが、インジェクションが必要なカスタムハンドラーがある場合は、これらのリクエストに対して「セッション」が存在しないため、いくつかの問題が発生します。
  4. Session_Endは常に起動するとは限りませんSessionStateModule.Endのドキュメントによると、プロセス外のセッション状態を使用すると、実際にはSession_Endイベントが取得されないため、クリーンアップできません。

制限があるため、通常、セッションに保存されたスコープに近づかないようにすることをお勧めします。しかし...それがあなたがやろうとしていることなら、ILifetimeScopeProviderそれがそれをする方法です。

于 2012-07-30T17:06:05.967 に答える