2009-05-06 15 views
6

Nel mio codice, ho le seguenti oggetti:Qual è il modo migliore per gestire le dipendenze circolari tra gli oggetti?

  • ErrorManager - controlla il modo in errori vengono registrati nell'applicazione
  • configmanager - controlla come si ottiene le informazioni di configurazione

On Nel progetto su cui sto lavorando, ErrorManager deve estrarre le informazioni di configurazione utilizzando l'istanza di ConfigManager mentre ConfigManager utilizza l'ErrorManager in caso di errore.

Al momento, sto facendo quanto segue in codice:

ErrorManager _errorManager = new CustomErrorManager(); 
ConfigManager _configManager = new CustomConfigManager(_errorManager); 
_errorManager.SetConfigurationManager(_configManager); 

C'è un modo per me per ripulire questo riferimento circolare delle dipendenze?

+2

Generalmente un'abbondanza di classi "Manager" indica un abuso del modello Singleton e non un design orientato agli oggetti. – Tmdean

+1

Sto utilizzando un modello Singleton per specifiche responsabilità nell'applicazione (ad esempio gestione degli errori e gestione della configurazione). L'istanza singola non è implementata tramite un pattern Factory poiché sto cercando di aggiungere un contenitore IOC nell'applicazione nel prossimo futuro per gestire le dipendenze per me. In questo momento, mi sto concentrando solo sul funzionamento delle dipendenze in modo che il contenitore IoC sia un'aggiunta facile. – JamesEggers

risposta

3

vorrei creare la seguente:

ErrorConfig _errorConfig = ...; 
// ErrorConfig is a new config object containing only ErrorManager Configuration 
ErrorManager _errorManager = new CustomErrorManager(_errorConfig); 
ConfigManager _configManager = new CustomConfigManager(_errorManager); 

Ora, il ConfigManager può può utilizzare il ready-to-run ErrorManager senza problemi il bootstrap in cui il ErrorManager non è pronto per gestire gli errori.

2

I riferimenti circolari di solito vengono ripuliti meglio rifattorizzando una terza classe da cui dipendono entrambi. Ad esempio, potresti avere qualcosa di simile a questo:

BootstrapConfigManager _bcm = new BootstrapConfigManager(); 
ErrorManager _errorManager = new CustomErrorManager(_bcm); 
ConfigManager _configManager = new CustomConfigManager(_bcm, _errorManager); 
0

Rif. Codice. Probabilmente puoi suddividere le classi per isolare una porzione che puoi inizializzare per prima e passare ad entrambe le classi.

0

Vorrei creare un metodo di estensione per ogni AddRelationship chiamato, passando l'altro oggetto come parametro.

L'oggetto passato aggiungerebbe il rapporto e quindi chiamare il metodo AddRelationship dell'altro:

static void AddRelationship(this ConfigManager configMgr, ErrorManager errMgr) 
{ 
    this.ErrorManager = errMgr; 
    if (this != errMgr.ConfigManager) 
     errMgr.AddRelationship(this); 
} 

static void AddRelationship(this ErrorManager errMgr, ConfigManager configMgr) 
{ 
    this.ConfigManager = configMgr; 
    if (this != configManager.errMgr) 
     configMgr.AddRelationship(this); 
} 

Questo significa che è possibile aggiungere il rapporto utilizzando oggetto.

ConfigManager cfg = new ConfigManager(); 
ErrorManager err = new ErrorManager(); 
//Assign using either: 
err.AddRelationship(cfg); 
//Or 
cfg.AddRelationship(err); 

È inoltre necessario creare estensioni RemoveRelationship.

static void RemoveRelationship(this ConfigManager configMgr, ErrorManager errMgr) 
{ 
    if (this.errorManager == errMgr) 
    { 
     this.errorManager = null; 
     if (errManager.configManager == this) 
      errMgr.RemoveRelationship(this); 
    } 
} 

static void RemoveRelationship(this ErrorManager errMgr, ConfigManager cfgMgr) 
{ 
    if (this.ConfigManager == cfgMgr) 
    { 
     this.configManager = null; 
     if (cfgMgr.errorManager == this) 
      cfgMgr.RemoveRelationship(this); 
    } 
} 

Non so che i riferimenti circolari sono un particolarmente buona pratica di codifica, ma questo dovrebbe risolvere la questione come chiesto.

+0

Mentre ciò funzionerebbe come una possibile soluzione, non funzionerebbe da un punto di vista del contenitore IoC da quello che posso dire; tuttavia, sto ancora imparando un paio di contenitori IoC diversi, quindi potrei sbagliarmi. – JamesEggers

+0

Ah, non l'hai specificato nella tua domanda originale o potrei non aver pubblicato. Non ho ancora avuto il tempo di esaminare i contenitori IoC o l'iniezione di dipendenza a causa di altri requisiti del progetto. – BenAlabaster

Problemi correlati