Come strutturare il mio progetto agnostico della GUI?

2

Ho un progetto che carica dal database un file XML che definisce un modulo per alcuni utenti. XML viene trasformato in una raccolta di oggetti le cui classi derivano da un singolo genitore. Qualcosa come

Controllo - > EditControl - > TextBox

Controllo - > ContainterControl - > Pannello

Queste classi sono responsabili della creazione di controlli GUI per tre diversi ambienti: WinForms, DevExpress XtraReports e WebForms. Tutti e tre i framework condividono principalmente la stessa struttura di controllo e hanno un singolo genitore comune (Windows.Forms.Control, XrControl e WebControl).

Quindi, come si fa?

Soluzione a) La classe di controllo ha metodi astratti

Control CreateWinControl();
XrControl CreateXtraControl();
WebControl CreateWebControl();

Questo potrebbe funzionare ma il progetto deve fare riferimento a tutti e tre i framework e le classi saranno grasse con metodi che supporterebbero tutte e tre le implementazioni.

Soluzione b) Ogni implementazione del framework viene eseguita in progetti separati e ha l'albero delle classi esatto come il progetto Core. Tutte e tre le implementazioni sono collegate usando un'interfaccia alla classe Core.

Questo sembra pulito ma sto attraversando un periodo difficile che mi avvolge la testa. Qualcuno ha una soluzione più semplice o un suggerimento come devo affrontare questa attività?

    
posta Nezreli 22.10.2013 - 14:19
fonte

2 risposte

1

Se hai un albero di oggetti (e intendo l'albero degli oggetti, non l'albero delle classi) di vari tipi che vuoi elaborare in modi diversi, allora l'approccio comune è usare lo schema dei visitatori .

Come ti sembrerebbe questo nel tuo caso? Il tuo progetto comune conterrebbe una classe astratta ControlTreeVisitor , che sarebbe simile a questa (semplificata assumendo che non ci sia ContainterControl o EditControl ):

public abstract class ControlTreeVisitor
{
    protected virtual void VisitControl(Control control)
    {
        // dispatch to the appropriate Visit* method
    }

    protected virtual void VisitPanel(Panel panel)
    {
        foreach (var childControl in panel.Children)
        {
            VisitControl(childControl);
        }
    }

    protected virtual void VisitTextBox(TextBox textBox)
    {
        // do nothing
    }
}

Ogni progetto specifico della GUI conterrà quindi una classe concreta che erediterebbe da questa classe visitatore e sovrascriverà tutti i metodi Visit* per creare l'albero di controllo appropriato per la libreria della GUI fornita.

Ci sono alcune possibili alternative nel design della classe base visitatore. Ad esempio, una variazione sarebbe quella di renderla generica, in cui il parametro type rappresenterebbe la classe base nella libreria della GUI specifica (ad esempio class WebControlVisitor : ControlTreeVisitor<WebControl> ). Tutti i metodi Visit* restituirebbero questo tipo. Questo renderebbe più semplice la creazione di un albero di WebControl s.

    
risposta data 22.10.2013 - 16:01
fonte
1

La soluzione (b) è la strada da percorrere. Definisci le interfacce per i vari controlli:

public interface EditControl
{
  //...
}

public interface ContainerControl
{
  //...
}

e un'interfaccia per una fabbrica:

public interface ControlFactory
{
  EditControl CreateEditControl(...);
  ContainerControl CreateContainerControl(...);
  //...
}

Ciascuno dei pacchetti implementerà quindi questo insieme di interfacce; in particolare, ogni pacchetto sa come implementare l'interfaccia ControlFactory creando il proprio gusto dei controlli.

    
risposta data 22.10.2013 - 16:17
fonte

Leggi altre domande sui tag