2009-05-15 15 views
6

私はデータを保持するために汎用リポジトリパターンを使用しています。 PageLoadでは、私は新しいリポジトリ(IRepositoryから)オブジェクトを作成しています。Pag​​eUnloadでは、そのオブジェクトを処分します。WebフォームとDIオブジェクトのインスタンス化を使用したMVPパターン

マスターページ/ページは、プレゼンターに渡すオブジェクトをインスタンス化するか、プレゼンターがこれを担当する必要がありますか?私は、プレゼンターに渡されたインターフェイスを模擬するほうが簡単だから、ページ(View)よりもプレゼンターをテストすることにもっと関心があります。

例Page

public partial class _Default : System.Web.UI.Page 
{ 
    private IRepository _repo; 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     if (_repo == null) 
      _repo = new Repository(); 
     ConnectPresenter(); 
    } 

    private void ConnectPresenter() 
    { 
     _DefaultPresenter presenter = new _DefaultPresenter(_repo); 
    } 

    private void Page_Unload(object sender, EventArgs e) 
    { 
     if (_repo != null) 
      _repo.Dispose(); 
    } 
} 

だろうな、この場合のStructureMapまたはNinjectヘルプなどDIフレームワーク?このようなオブジェクトを処分することは、それが担当するでしょうか?

答えて

6

Pageクラスも発表者も、依存関係の構築やライフサイクルの管理に直接取り組まなくてはなりません。そのすべては、コンテナで処理する必要があります。コンストラクタインジェクションはWebFormsでは動作しないので、必要な依存関係をクラスのプロパティとして公開する必要があります。たとえば、あなたがあなたのクラスを変更することができます:それはプレゼンターに注入されるように

public partial class _Default : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
    } 

    public _DefaultPresenter Presenter { get; set; } 
} 

ページには、リポジトリへの参照を必要はありません。

この回答の残りの部分はStructureMapに固有のものです。詳細は他の容器と異なる場合があります。

セッター注入を有効にするには、どのプロパティを設定するかをStructureMapに指示する必要があります。 1つの方法は、プロパティ自体に[SetterProperty]属性を適用することです。しかし、これはあなたのクラス内でStructureMapの詳細を少し侵略的に感じることができます。別の方法は、どのプロパティタイプを注入するかを知るようにStructureMapを設定することです。たとえば、

protected void Application_Start(object sender, EventArgs e) 
{ 
    ObjectFactory.Initialize(x => 
    { 
     x.Scan(scan => 
     { 
      scan.TheCallingAssembly(); 
      scan.WithDefaultConventions(); 
     }); 
     x.ForRequestedType<IRepository>().TheDefaultIsConcreteType<Repository>().CacheBy(InstanceScope.Hybrid); 
     x.SetAllProperties(set => set.WithAnyTypeFromNamespaceContainingType<IRepository>()); 
    }); 
} 

SetAllPropertiesメソッドを使用すると、構造マップに入力するプロパティを認識する方法を指定できます。この場合、私はすべてのプレゼンターを(それらがすべて同じ名前空間にあると仮定して)注入するようにStructureMapに指示しています。

各リクエストでセッター注入を実行する必要があります。StructureMapでは、BuildUp()メソッドを使用して既存のインスタンスに依存関係を注入します。各ページのInitイベントまたはLoadイベント、またはページベースクラスで行うことができますが、侵入していると感じます。完全にあなたのページのクラスのうち、コンテナを維持するには、(Global.asaxのかのIHttpModuleで)アプリケーションのPreRequestHandlerExecuteイベントを使用することができます。最後に

protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) 
{ 
    var application = (HttpApplication)sender; 
    var page = application.Context.CurrentHandler as Page; 
    if (page == null) return; 
    ObjectFactory.BuildUp(page); 
} 

、あなたが明示的にあなたのIRepositoryを処分したい場合は、初期設定では、我々があれば、「各HTTPリクエスト(またはスレッドのために私に同じインスタンスを与えることを意味する、ハイブリッドでIRepositoryをキャッシュするのStructureMapを告げたので、これは正しく動作していること

protected void Application_EndRequest(object sender, EventArgs e) 
{ 
    var disposable = ObjectFactory.GetInstance<IRepository>() as IDisposable; 
    if (disposable != null) disposable.Dispose(); 
} 

注:EndRequestのイベントでそれを扱うことができますウェブサイト内では実行されません)。 EndRequestでIRepositoryを取得すると、要求全体で同じIRepositoryを受け取り、処分することができます。

2

はい、あなたが調査する価値があるでしょうone of the walkthroughs out there of using DI with ASP.NET

はい、要求ごとの動作オブジェクトを適切なポイントに配置することは、通常、コンテナとASP.NETの統合によって管理されます。

典型的な配置は、オブジェクトの作成がページから流れ込み、内向きに行われることです。一般に、Pageクラスのプロパティ[Inject]にマークを付けますが、トライアドをどのように配置したかによって異なります。プレゼンターは一般的にConstructo Injectionを使用して、テストまたはASP.NETのいずれのコテックスに関係なく、必要なものを宣言することができます。実行時に依存関係はDIによって満たされます。テスト時にはまだDIを使用することができますが、他のケースではSUTと共にFakeの束を作成してプレゼンターに渡すのがより自然かもしれません。

トライドアレンジについては、this MSDN Mag article on using Ninject with xUnit.net by Justin Etheredgeは、ASP.NET MVCをターゲットにしていても非常に便利です。

+0

ご質問のコードやタグを見ないと申し訳ありません。問題を改善することを願っています。あなたがあなたを削除した場合、これを削除します... –

関連する問題