6

モデル ビュー プレゼンター パターンの独自のコピーを (Web クライアント ソフトウェア ファクトリに沿って) 実装したので、多くの問題を抱えていた WCSF の ObjectBuilder に縛られる代わりに、独自の DI フレームワークを活用できます。私はそれを行うためのいくつかの方法を思いつきましたが、特に私を幸せにする方法はありません. 他の誰かが他のアイデアを持っているかどうか知りたかった.

解決策 #1a

HttpModule を使用して context.PreRequestHandlerExecute をインターセプトし、ObjectFactory.BuildUp(HttpContext.Current.Handler) を呼び出します。

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    private EmployeePresenter Presenter
    {
        set
        {
            _presenter = value;
            _presenter.View = this;
        }
    }
}

解決策 #1b

HttpModule を使用する代わりに、ページの読み込み時に buildup を呼び出す

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    private EmployeePresenter Presenter
    {
        set
        {
            _presenter = value;
            _presenter.View = this;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        ObjectFactory.BuildUp(this);
    }
}

解決策 #1c

Property を介してプレゼンターにアクセスし、必要に応じて Getter を BuildUp できるようにします。

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    public EmployeePresenter Presenter
    {
        get
        {
            if (_presenter == null)
            {
                ObjectFactory.BuildUp(this);
            }

            return _presenter;
        }
        set
        {
            _presenter = value;
            _presenter.View = this;
        }
    }
}

解決策 2

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    private EmployeePresenter Presenter
    {
        get
        {
            if (_presenter == null)
            {
                _presenter = ObjectFactory.GetInstance<EmployeePresenter>();
                _presenter.View = this;
            }

            return _presenter;
        }
    }
}

解決策 2b

public partial class _Default : Page, IEmployeeView
{
    private EmployeePresenter _presenter;

    private EmployeePresenter Presenter
    {
        get
        {
            if (_presenter == null)
            {
                Presenter = ObjectFactory.GetInstance<EmployeePresenter>();
            }

            return _presenter;
        }
        set
        {
            _presenter = value;
            _presenter.View = this;
        }
    }
}

編集:ソリューション1c、2bを追加

4

4 に答える 4

7

ソリューション #1b を使用し、プレゼンターの初期化をもう少し DRY するために、すべてのページのレイヤー スーパータイプを作成します。このような:

ページコード:

public partial class _Default : AbstractPage, IEmployeeView
{
    private EmployeePresenter presenter;

    private EmployeePresenter Presenter
    {
        set
        {
            presenter = value;
            presenter.View = this;
        }
    }
    protected override void Do_Load(object sender, EventArgs args)
    {
        //do "on load" stuff 
    }

}

抄録ページのコード:

public abstract class AbstractPage : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ObjectFactory.BuildUp(this);
        this.Do_Load(sender,e); 
        //template method, to enable subclasses to mimic "Page_load" event

    }
    //Default Implementation (do nothing)
    protected virtual void Do_Load(object sender, EventArgs e){}
}

このソリューションを使用すると、プレゼンターの初期化 (ObjectFactory によって作成される) を 1 つのクラスのみで行うことができます。後で変更する必要がある場合は、簡単に行うことができます。

編集:

Do_Load は抽象仮想か?

Template Methodはもともと、サブクラスにメソッドを実装させ、スーパークラスの規約を遵守させるために、メソッドは抽象でなければならないと述べています。(ウィキペディアの「モノポリー」<「ゲーム」の例を参照)。

一方、この特定のケースでは、ユーザー クラスに強制的にメソッドを再定義させたくはありませんが、そうする機会を与えます。それをabstractと宣言すると、多くのクラスはメソッドを空のままにするためにメソッドを再定義しなければならなくなります(これは明らかにコードの匂いです)。したがって、適切なデフォルト (何もしない) を提供し、メソッドを仮想化します。

于 2009-02-10T05:38:41.873 に答える
1

私はベースページクラスを次のように使用しています:

protected override void OnInit(EventArgs e)
    {
        StructureMap.ObjectFactory.BuildUp(this);
        base.OnInit(e);
    }

基本クラスのアプローチはユーザー コントロールでも機能し、それだけで私はモジュールから遠ざかりました (2 つの方法でセットアップする必要はありませんでした)。ページの場合は

public partial class Employee : View, IEmployeeView
{
    public ViewPresenter Presenter { get; set; }
    private void Page_Load(object sender, EventArgs e){}
}

コンストラクターを介してビューを挿入します。構造マップ構成での循環参照の問題を回避するには、次のヘルパー メソッドを使用します。

static T GetView<T>()
{
    return (T) HttpContext.Current.Handler;
}

構造マップ構成では、プレゼンターとビュー インジェクションの両方に規則を使用します。

于 2009-02-14T08:02:52.360 に答える
0

皆様、大変貴重なご意見をありがとうございました。あなたの答えはそれぞれ、私の最終的な解決策で組み合わせる貴重なアイデアを私に与えてくれました。これが私が思いついたものです:

public abstract class ViewBasePage<TPresenter, TView> :
    Page where TPresenter : Presenter<TView>
{
    protected TPresenter _presenter;

    public TPresenter Presenter
    {
        set
        {
            _presenter = value;
            _presenter.View = GetView();
        }
    }

    /// <summary>
    /// Gets the view. This will get the page during the ASP.NET
    /// life cycle where the physical page inherits the view
    /// </summary>
    /// <returns></returns>    
    private static TView GetView()
    {
        return (TView) HttpContext.Current.Handler;
    }

    protected override void OnPreInit(EventArgs e)
    {
        ObjectFactory.BuildUp(this);
        base.OnPreInit(e);
    }
}

そして、私の元のページに継承されました:

public partial class _Default : 
    ViewBasePage<EmployeePresenter, IEmployeeView>, IEmployeeView
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            _presenter.OnViewInitialized();
        }

        _presenter.OnViewLoaded();
        Page.DataBind();
    }

    #region Implementation of IEmployeeView

    ...

    #endregion
}
于 2009-02-15T21:41:38.050 に答える