Question

J'ai mis ma propre copie de la vue du modèle modèle de présentateur (dans la veine de l'usine de logiciel client Web) Je peux tirer parti de mon propre cadre de DI au lieu d'être lié à ObjectBuilder de WCSF que j'ai eu de nombreux problèmes avec. Je suis venu avec quelques moyens de le faire, mais aucun d'entre eux en particulier me rendre heureux. Je voulais savoir si quelqu'un d'autre avait d'autres idées.

Solution # 1a

Utilise HttpModule pour intercepter context.PreRequestHandlerExecute appeler ObjectFactory.BuildUp (HttpContext.Current.Handler)

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

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

Solution # 1b

accumulation d'appel à chargement de la page au lieu d'utiliser un HttpModule

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);
    }
}

Solution # 1c

présentateur d'accès par la propriété permet getter BuildUp si nécessaire.

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;
        }
    }
}

Solution # 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;
        }
    }
}

Solution # 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;
        }
    }
}

Modifier : solution ajoutée 1c, 2b

Était-ce utile?

La solution

J'utiliserions solution # 1b, et créer un supertype pour toutes les pages, afin de sécher l'initialisation du présentateur un peu plus. comme ceci:

Code de la page:

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 
    }

}

Code page Résumé:

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){}
}

Avec cette solution, vous avez l'initialisation du présentateur (créé par le ObjectFactory) dans une seule classe, si vous avez besoin de le modifier plus tard, vous pouvez le faire facilement.

Modifier

devrait être Do_Load abstrait ou virtuel

Template Method indique l'origine que le procédé devrait être abstrait, afin de forcer les sous-classes pour mettre en œuvre elle, en adhérant au contrat de superclasse. (Voir l'exemple de wikipedia "Monopoly" < "Game").

D'autre part, dans ce cas particulier, nous ne voulons pas forcer la classe utilisateur de redéfinir notre méthode, mais lui donner la chance de le faire. Si vous déclarez abstraite, de nombreuses classes seront obligés de redéfinir la méthode juste pour le laisser vide (ce qui est clairement une odeur de code). Nous offrons donc un défaut raisonnable (ne rien faire) et faire la méthode virtuelle.

Autres conseils

Je l'ai construit mon propre cadre MVP comme ça aussi. J'ai trouvé la meilleure façon pour moi était d'utiliser les médicaments génériques avec une classe de page de base. En spécifiant le type présentateur dans la définition de classe générique, je peux manquer la plupart du code qui chacun de vos propositions exige.

Cependant, il y a des choses que je n'aime pas le faire de cette façon. La définition de classe peut finir par un peu compliqué, et il est pas facile à lire pour un débutant. J'ai pas complètement travaillé une bonne façon d'utiliser le modèle d'événement dans la page de base.

Désolé, je n'ai pas le code pour vous ici, mais je peux poster un peu pour vous si vous le souhaitez. J'ai aussi une ancienne version du code affiché à www.codeplex.com/aspnetmvp, si vous voulez voir comment cela fonctionne.

J'utilise une classe de page de base avec:

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

L'approche de classe de base fonctionne sur le contrôle de l'utilisateur ainsi que seul m'a empêché de le module (ne voulait pas avoir 2 façons de le mettre en place). Pour la page, il est

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

J'Injecter la vue par le constructeur. Pour éviter le problème de référence circulaire sur la configuration StructureMap, il suffit d'utiliser cette méthode d'assistance:

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

Sur la config StructureMap utiliser une convention tant pour le présentateur et l'injection de vue.

Merci à tous pour votre contribution très précieuse. Vos réponses chacun m'a donné des idées précieuses à combiner ensemble dans ma solution finale et ce que je suis venu avec:

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);
    }
}

Et hérité de ma page originale:

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
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top