Applicazione desktop, iniezione dipendenza

3

Sto pensando di applicare una vera libreria di dipendenze per l'iniezione alla mia applicazione desktop C # / GTK # giocattolo. Ho scelto NInject , ma penso che questo sia irrilevante per la mia domanda.

C'è un oggetto di database, una finestra principale e diverse classi di finestre di utilità. È chiaro che posso iniettare il database in ogni oggetto della finestra, quindi qui DI è utile. Ma ha senso iniettare classi di finestre di utilità in altre classi di finestre?

Esempio: ho classi come:

class MainWindow {…}
class AddItemWindow {…}
class AddAttachmentWindow {…}
class BrowseItemsWindow {…}
class QueryBuilderWindow {…}
class QueryBrowserWindow {…}
class PreferencesWindow {…}
…

Ciascuna classe di utilità può essere aperta da MainWindow. Alcune finestre di utilità possono essere aperte anche da altre finestre di utilità. In generale, potrebbe esserci un grafico davvero complesso di chi può aprire chi. Quindi ognuna di queste classi potrebbe aver bisogno di un sacco di altre classi di finestre iniettate. Sono preoccupato che tale uso vada contro il suggerimento di non iniettare troppe lezioni contemporaneamente e diventare un odore di codice. Dovrei usare qualche tipo di oggetto locator di servizio qui?

    
posta liori 15.12.2012 - 20:59
fonte

2 risposte

2

Suggerirei una classe UtilityWindowOpener . I suoi metodi apriranno le varie finestre di utilità. Quindi puoi semplicemente iniettare un UtilityWindowOpener ovunque tu possa aver bisogno di aprire una finestra di utilità. Il UtilityWindowOpener avrà quindi le varie finestre di utilità iniettate (o eventualmente le creeranno su richiesta, che è nascosta dietro l'interfaccia). Trasformerà inoltre tutte le logiche di navigazione in meno posizioni.

    
risposta data 15.12.2012 - 21:45
fonte
0

Per evitare la sovrainiezione invece di iniettare tutti gli oggetti Window di classi * Window in MainWindow potresti usare Ninject.Extension.Factory . In questo caso Abstract Factory potrebbe avere la seguente interfaccia:

public interface IWindowFactory
{
    AddItemWindow CreateAddItemWindow();
    AddAttachmentWindow CreateAddAttachmentWindow();
    /* etc */
}

E poi aggiungi associazione a Load implementazione di Ninject.NinjectModule :

Bind<AddItemWindow>()
    .ToSelf()
    .NamedLikeFactoryMethod<AddItemWindow, IWindowFactory>(f => f.CreateIWindowFactory());

Bind<AddAttachmentWindow>()
    .ToSelf()
    .NamedLikeFactoryMethod<AddItemWindow, IWindowFactory>(f => f.CreateIWindowFactory());

/* etc */

// and factory binding
Bind<IWindowFactory>()
    .ToFactory()
    .InSingletonScope();

Due punti aggiuntivi:

  • C'è un articolo eccellente di Mark Seemann Riconoscimento pattern: Abstract Factory o Service Locator? - quindi questa soluzione è ok, se ti interessa Serice Locator anti-pattern, e ...
  • Per renderlo al 100% non l'anti-pattern Serice Locator assicurati che Abstract Factory crei solo oggetti Windows, non tutto.
risposta data 15.12.2012 - 22:15
fonte