Visualizzazione di una vista da un'altra vista in MVP

7

Questa domanda riguarda le triadi MVP. Diciamo che ho due triadi e il primo ha View1 , Mode1 e Presenter1 . La seconda triade ha View2 , Model2 e Presenter2 . Ora, quello che sto cercando di fare è, voglio solo mostrare View2 quando clicco su button in View1 .

Mostreresti il View1 che chiama il metodo show del presentatore.

View1Presenter presenter1 = new View1Presenter (view1, Model1);
presenter1.show();

Ora, quando faccio clic sul pulsante btnShowView2 su View1 , dovrebbe visualizzare View2 .

Quindi come chiamare presenter2.show() da View1 ?

    
posta CAD 16.06.2014 - 06:13
fonte

1 risposta

5

La visualizzazione di una seconda vista su btnShowView2.Clicked è una sorta di logica aziendale, quindi il posto giusto per l'implementazione è nel gestore eventi di presenter1 che si occupa di quell'evento (presumo che presenter1 sia registrato a tutti i pulsanti pertinenti -click eventi di View1 ). Lo chiamo HandleBtnView2Click , quindi il codice iniziale all'interno di quel gestore potrebbe essere simile a questo:

  void HandleBtnView2Clicked(object sender, EventArgs e))
  {
       IView2 view2 = new View2();
       Model2 model2 = model1.GetRefToModel2(); // or whatever is needed to get model2
       View2Presenter presenter2 =new View2Presenter(view2,model2);
       presenter2.show();
  }

In realtà, questa non è una buona soluzione, dal momento che implicherebbe che il livello presenter2 debba essere collegato alla libreria UI (nel tuo caso WinForms), che nel peggiore dei casi impedisce il test automatico.

La soluzione migliore è delegare la creazione di View2 a una terza istanza, che può essere facilmente derisa. In generale, è possibile utilizzare una fabbrica astratta per questo. Nel caso specifico, è anche possibile utilizzare View1 per la creazione di View2 . Aggiungi un metodo all'interfaccia IView1 :

 interface IView1
 {
    // ...
      IView2 CreateView2();
 }

e usalo nel codice sopra:

  void HandleBtnView2Clicked(object sender, EventArgs e))
  {
       IView2 view2 = view1.CreateView2(); // view1 is of type IView1 and a member of presenter1
       Model2 model2 = model1.GetRefToModel2(); // or whatever is needed to get model2
       View2Presenter presenter2 =new View2Presenter(view2,model2);
       presenter2.show();
  }

Ora, quando vuoi testare automaticamente il tuo presenter1 , fornisci un'implementazione fittizia di view1 che implementa il metodo CreateView2 in un modo che restituisce un mock of view2. Nella classe View1 , si implementa CreateView2() per restituire new View2() , quindi la responsabilità per la creazione delle viste rimane nel livello vista.

Puoi fare un ulteriore passo avanti se vuoi e rendere presenter1 testabile in isolamento da presenter2 . Se pensi che sia necessario, crea un'interfaccia IPresenter2 e metti l'intero codice di creazione sopra in un astratto "presenter factory":

   void HandleBtnView2Clicked(object sender, EventArgs e))
   {
        IPresenter presenter2 = presenterFactory.CreatePresenter2(model1);
        presenter2.show();
   }

Il presenterFactory deve essere iniettato nel tuo presenter1 in fase di costruzione e può essere sostituito da una simulazione nella tua suite di test. Se è necessario, devi decidere tu stesso. Aggiungerà un ulteriore livello di complessità al tuo codice a vantaggio di una migliore testabilità.

    
risposta data 16.06.2014 - 09:46
fonte

Leggi altre domande sui tag