Iniezione di dipendenza: dove archiviare le dipendenze utilizzate da un solo metodo?

2

Sto sviluppando un progetto integrato con Dependency Injection (solo per riferimento, sto usando Unity).

Il problema è che ho alcune classi Manager con diversi metodi e in molti casi ho delle dipendenze usate solo in un metodo.

public class UserReportManager : IUserManager
{
    private UserRepository  UserRepository  {get;set;}
    private TeamRepository   TeamRepository   {get;set;}
    private CacheRepository   CacheRepository   {get;set;}
    private WorkgroupRepository   WorkgroupRepository   {get;set;}

    public UserManager(UserRepository userRepository,
                       TeamRepository teamRepository,
                       CacheRepository cacheRepository ,
                       WorkgroupRepository workgroupRepository,
                       ... // Many other dependencies 
                      )
    {
        UserRepository  = userRepository;
        TeamRepository = teamRepository;
        CacheRepository = cacheRepository ;
        WorkgroupRepository = workgroupRepository;  
        ... // Setting the remaining dependencies
    }

    public void CreateReportAboutMostActivesUsers(){
        // Uses only UserRepository  
    }

    public void CreateReportAboutUserInsideTeams(int teamID){
        // Uses UserRepository and TeamRepository 
    }

    public void CreateReportAboutUserHistory(){
        // Uses UserRepository and CacheRepository 
    }

    public void CreateReportAboutUsersInsideWorkgroup(int workgroupID){
        // Uses UserRepository and WorkgroupRepository 
    }
}

L'UserManager è istanziato in questo modo:

DependencyFactory.Resolve<IUserManager>(); 

Nota: DependencyFactory è solo un wrapper per semplificare l'accesso a UnityContainer

È corretto avere classi del genere nell'esempio? C'è un modo migliore per implementare evitando di istanziare tutte le dipendenze non necessarie?

    
posta simoneL 22.08.2014 - 11:58
fonte

2 risposte

2

Perché è lo scopo di questa classe UserManager ?, puoi utilizzare i tuoi repository direttamente quando ne hai bisogno. Il nome "Manager" è normalmente e consiglia a una classe con molte o poco chiare responsabilità, chissà cosa fa un "manager"?.

Un'altra cosa sembra un po 'strana nel tuo progetto, come se stessimo creando un repository per tabella o storage (questo repository cache) più di un repository per entità / aggregato come la proposta originale in Domain Driven Design.

Ad esempio, si ha un Repository di team invece di avere un metodo findByTeam nel repository utente. Mi aspetto che un Repository di team mi restituisca "team" e non utenti. Pensa in un repository come un'astrazione per accedere all'entità utente qualunque sia realmente questo utente. All'interno di questa implementazione di repository è possibile accedere a diverse tabelle o sistemi di archiviazione per ottenere quegli utenti.

Riguardo alla domanda originale, in generale se hai dipendenze N in una classe e ciascuna dipendenza è usata solo in un metodo hai un problema di coesione nella tua classe, questo è un sintomo sbagliato, è un "allarme" per rivedere la tua design.

    
risposta data 22.08.2014 - 13:40
fonte
-1

Non hai bisogno di un gestore utenti, quello che ti serve è creare un'interfaccia per ciascun repository.

Quindi avrai IUserRepository, ITeamRepository e prosegui.

Dopo che devi separare la logica dalla fabbrica usando due diversi progetti, io uso per chiamare il progetto logico DAL e il factory Resolver. Devi farlo perché se ad esempio stai usando Sql Server per accedere ai tuoi repository e per qualche motivo decidi di usare EF devi riscrivere il codice Factory che è sbagliato. Factory deve essere generico, quindi se decidi di usare EF devi solo creare un nuovo DAL, usando le stesse interfacce e usa solo la logica EF, dopodiché farai riferimento al nuovo DAL invece del vecchio nel progetto Factory e tutto funzionerà di nuovo.

Quindi creare un progetto DAL, creare una classe per ogni repository che eredita dall'interfaccia corretta (le interfacce devono essere in un terzo progetto che utilizzo per chiamare le dipendenze e devono essere referenziate da DAL e Resolver) aggiungere all'interfaccia i metodi Iscriviti per i metodi che ti servono come:

public interface IUserRepository
{
    void GetLatestUser(); // get with void makes no sense
}

che nella tua fabbrica tutto ciò di cui hai bisogno è solo per registrare l'interfaccia con l'implementazione:

container.RegisterType<IUserRepository, UserRepository>();

PS: non ti serve questo:

public class DependencyFactory<T> //but just

public static class DependencyFactory

E alla fine per ottenere il tuo repository hai solo bisogno di aggiungere questa funzione alla tua fabbrica:

public static T Resolve<T>()
{
    var result = default(T);

    if (Container.IsRegistered(typeof(T)))
    {
        result = Container.Resolve<T>();
    }

    return result;
}
    
risposta data 22.08.2014 - 13:01
fonte

Leggi altre domande sui tag