Domanda

Ho implementato la mia copia del modello presentatore vista del modello (in vena di web client software factory) in modo da poter sfruttare la mia quadro DI, invece di essere legato a ObjectBuilder di WCSF che ho avuto numerosi problemi con. Mi è venuta in mente un paio di modi per farlo, ma nessuno di loro in particolare mi fanno felice. Volevo sapere se qualcun altro ha avuto alcune altre idee.

Soluzione # 1 bis

Utilizza una HttpModule per intercettare context.PreRequestHandlerExecute chiamare ObjectFactory.BuildUp (HttpContext.Current.Handler)

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

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

Soluzione # 1b

Chiamata accumulo di caricamento della pagina, invece di utilizzare 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);
    }
}

Soluzione # 1c

presentatore di accesso attraverso la proprietà permettono Getter di accumulo, se necessario.

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

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

Soluzione # 2 ter

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

Modifica : Aggiunto soluzione 1c, 2b

È stato utile?

Soluzione

mi piacerebbe utilizzare la soluzione # 1b, e creare un supertipo per tutte le pagine, per asciugare l'inizializzazione presentatore un po 'di più. in questo modo:

Codice Pagina:

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 
    }

}

Estratto di codice Pagina:

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

Con questa soluzione si ha l'inizializzazione presentatore (creato dal ObjectFactory) in una sola classe, se è necessario modificare in un secondo momento si può fare facilmente.

Modifica

Dovrebbe Do_Load essere abstract o virtual

Template Method afferma inizialmente che il metodo dovrebbe essere astratta, al fine di costringere sottoclassi di implementare essa, aderendo al contratto superclasse. (Vedi wikipedia esempio di "Monopoly" < "Gioco").

D'altra parte in questo caso particolare, non vogliamo forzare la classe utente per ridefinire il nostro metodo, ma diamo la possibilità di farlo. Se si dichiara astratto, molte classi saranno obbligati a ridefinire il metodo giusto per lasciarla vuota (questo è chiaramente un odore di codice). Così forniamo un default ragionevole (non fare nulla) e facciamo il metodo virtuale.

Altri suggerimenti

Ho costruito il mio quadro di MVP del genere anche. Ho trovato il modo migliore per me è stato quello di utilizzare farmaci generici con una classe di pagina di base. Specificando il tipo di presentatore nella definizione della classe generica, riesco a perdere la maggior parte del codice che ciascuna delle vostre proposte richiede.

Tuttavia, ci sono alcune cose che non mi piacciono di fare in questo modo. La definizione di classe può finiscono per guardare piuttosto complicato, e non è facile da leggere per un newbie. Anche io non ho completamente elaborato un buon modo per utilizzare il modello di eventi nella pagina di base.

Mi dispiace non ho il codice per voi qui, ma posso postare alcuni per voi, se lo si desidera. Ho anche una vecchia versione del codice pubblicato su www.codeplex.com/aspnetmvp, se si vuole vedere come funziona.

Sono stato con una classe di pagina di base con:

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

L'approccio classe di base funziona su controlli utente pure, che da sola mi ha tenuto dal modulo (non voleva avere 2 modi per configurarlo). Per la pagina è

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

I iniettare la vista attraverso il costruttore. Per evitare il problema di riferimento circolare sulla configurazione StructureMap, basta usare questo metodo di supporto:

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

Nella configurazione StructureMap utilizzare una convenzione sia per il presentatore e l'iniezione vista.

Grazie a tutti per il vostro contributo molto prezioso. Le vostre risposte ciascuno mi ha dato idee preziose per combinare insieme nella mia soluzione finale e questo è ciò che mi si avvicinò con:

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

E ereditato dalla mia pagina 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
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top