Eliminazione della dipendenza ciclica

3

Voglio evitare la dipendenza ciclica in questo schema:

DbRepository ha bisogno di IUserDbEntityFactory per creare User entità che ha bisogno di IUserPublishedInfoInitializer per creare UserPublishedInfo su richiesta. E UserPublishedInfoInitializer stessa ha bisogno di IDbRepository per verificare se l'utente è attualmente presente nella cache e attivo per impostare la proprietà IsOnline su UserPublishedInfo .

Entrambi i metodi CreateUser e TryGetCachedUser utilizzano le stesse cose interne come la memorizzazione nella cache e i blocchi all'interno di DbRepository .

User è un'entità db radice di aggregazione senza interfaccia.

DbRepository richiede IUserDbEntityFactory che richiede IUserPublishedInfoInitializer per costruire User e riporta la dipendenza ciclica a DbRepository . Di solito uso l'iniezione della dipendenza del costruttore, ma in questo caso non funzionerà a causa della dipendenza ciclica, quindi questa è la domanda.

Inoltre, non voglio spostare MakePublishedInfo su User perché in effetti è una conversazione implicita in C # e viene usata molto frequentemente nel codice.

E passare IDbRepository a IUserPublishedInfoInitializer.Init come argomento non è né cosa voglio perché perché questa implementazione dovrebbe dipendere da cosa la sta usando? Questo rompe l'incapsulamento.

Solo sullo schema User e UserPublishedInfo sono oggetti creati dinamicamente (altri vengono creati all'avvio).

Dovrei cambiare questo disegno e come dovrebbe essere?

    
posta Vlad 03.08.2016 - 14:12
fonte

2 risposte

1

Vorrei rimuovere la dipendenza di IUserPublishedInfoInitializer su IDbRepository. Invece iniettalo come parametro di costruzione nel concreto UserPublishedInfoInitializer.

il tuo grafico delle dipendenze sarà quindi

IUserPublishedInfoInitializer
    IUserDbEntityFactory 
    User
        IDbRepository
            DbRepository
            UserPublishedInfoInitializer

modifica -

OK hai solo bisogno di un costruttore speciale su DbRepository o classe figlio

public DbRepository()
{
    var upii = new UserPublishedInfoInitializer(this);
    var this.userDbEntityFactory = new UserDbEntityFactory(upii);
}

se lo vuoi ancora tramite DI potresti avere un DbRepositoryFactory per fare la stessa cosa

public class DbRepositoryFactory : IDbRepositoryFactory 
{
    pulbic DbRepository Repo {get;set;}
}

public UserPublishedInfoInitializer(IDbRepositoryFactory repo)
{
    var this.DbRepositoryFactory= repo.Repo; //dont use this yet!!!
}

public Main()
{
    var dbfac = new DbRepositoryFactory()
    var upii = new UserPublishedInfoInitializer(dbfac);
    var repo = new DbRepository(upii)
    dbfac.Repo = repo;
}

Tuttavia, non sono sicuro che iniettare ALTRE cose è di grande aiuto per il tuo problema principale che sta rendendo l'oggetto User non modificabile senza un repository.

difficile da dire senza vedere l'intero problema ma, proprio dalla denominazione sembra che UserPublishedInfoInitializer non sia necessario, il repository potrebbe assumersi la responsabilità della creazione dell'oggetto UserPublishedInfo se User è efficacemente la radice aggregata e ha sempre una proprietà UserPublishedInfo

    
risposta data 03.08.2016 - 14:49
fonte
0

La soluzione ubiquitaria al problema della dipendenza circolare consiste nell'introdurre il modello di osservatore. Un'implementazione consiste nell'utilizzare eventi di dominio.

Se pensi che sia troppo, prova a iniettare la dipendenza IDbRepository nella classe UserPublishedInfoInitializer tramite l'iniezione di proprietà. Con puro DI avresti qualcosa di simile

var upi = new UserPublishedInfoInitializer();
var fac = new UserDbEntityFactory(upi);
var repo = new DbRepository(fac);
upi.DbRepository = repo;

Tuttavia questa è l'ultima soluzione consigliata.

Penso che puoi rompere la dipendenza circolare se rimuovi il metodo TryGetCachedUser nella sua interfaccia ( IUserCache ). DbRepository si assicura che l'utente sia inserito nella cache e UserPublishedInfoInitializer può ispezionare se un utente è nella cache.

    
risposta data 10.08.2016 - 15:30
fonte