2014-09-02 13 views
6

Presenterò questa domanda con la frase: so che il seguente è un cattivo design, ma il refactoring non è attualmente un'opzione, idealmente dovrebbe essere fatto usando gli intercettori.Qual è la differenza tra una dipendenza del componente e di un servizio?

Sto lavorando all'aggiornamento del castello da 1.6 (credo) a 3.3 che sfortunatamente comporta alcune modifiche alla sintassi, ora ho tutto in fase di compilazione ma alcuni dei miei test intorno al contenitore dei servizi non funzionano.

Ho un repository che ha diverse implementazioni per fornire funzionalità differenti, il repository è sempre e solo utilizzato con tutte le diverse implementazioni in linea, qui sono i principi fondamentali del codice:

The Windsor Castle registrazioni:

RepositoryRegistration<IAccountRepository, AccountRepositoryFeedEntryDecorator>() 
    .DependsOn(Dependency.OnComponent("decoratedRepository", typeof(AccountRepositoryAuthorizationDecorator))), 
RepositoryRegistration<AccountRepositoryAuthorizationDecorator>() 
    .DependsOn(Dependency.OnComponent("decoratedRepository", typeof(AccountRepositoryMaskingDecorator))), 
RepositoryRegistration<AccountRepositoryMaskingDecorator>() 
    .DependsOn(Dependency.OnComponent("decoratedRepository", typeof(AccountRepository))), 
RepositoryRegistration<AccountRepository>()); 

procedimento RepositoryRegistration:

private static ComponentRegistration<TRepository> RepositoryRegistration<TRepository, TConcreteRepository>() 
    where TConcreteRepository : TRepository where TRepository : class 
{ 
    return Component 
       .For<TRepository>() 
       .ImplementedBy<TConcreteRepository>()      
       .Named(typeof(TConcreteRepository).Name); 
} 

interfaccia di base:

public interface IAccountRepository 
{ 
    string Create(Account account); 
    void Update(Account account); 
    Account Get(string accountId); 
} 

Le implementazioni:

public class AccountRepositoryFeedEntryDecorator : IAccountRepository 
{ 
    private readonly IAccountRepository decoratedRepository; 
    public AccountRepositoryFeedEntryDecorator(
     IAccountRepository decoratedRepository) 
    { 
     this.decoratedRepository = decoratedRepository; 
    } 

    string Create(Account account) 
    { 
     //Add Entry To Feed 
     return decoratedRepository.Create(account); 
    }; 

    void Update(Account account) 
    { 
     //Add Entry To Feed 
     return decoratedRepository.Udpate(account); 
    } 
    Account Get(string accountId); 
    { 
     //Add Entry To Feed 
     return decoratedRepository.Get(accountId); 
    } 
} 

public class AccountRepositoryAuthorizationDecorator : IAccountRepository 
{ 
    private readonly IAccountRepository decoratedRepository; 
    public AccountRepositoryAuthorizationDecorator(
     IAccountRepository decoratedRepository) 
    { 
     this.decoratedRepository = decoratedRepository; 
    } 

    string Create(Account account) 
    { 
     //Ensure User Is Authorized 
     return decoratedRepository.Create(account); 
    }; 

    void Update(Account account) 
    { 
     //Ensure User Is Authorized 
     return decoratedRepository.Udpate(account); 
    } 
    Account Get(string accountId); 
    { 
     //Ensure User Is Authorized 
     return decoratedRepository.Get(accountId); 
    } 
} 

public class AccountRepositoryMaskingDecorator : IAccountRepository 
{ 
    private readonly IAccountRepository decoratedRepository; 
    public AccountRepositoryMaskingDecorator(
     IAccountRepository decoratedRepository) 
    { 
     this.decoratedRepository = decoratedRepository; 
    } 

    string Create(Account account) 
    { 
     //Mask Sensitive Information 
     return decoratedRepository.Create(account); 
    }; 

    void Update(Account account) 
    { 
     //Mask Sensitive Information 
     return decoratedRepository.Udpate(account); 
    } 
    Account Get(string accountId); 
    { 
     //Mask Sensitive Information 
     return decoratedRepository.Get(accountId); 
    } 
} 

public class AccountRepository : IAccountRepository 
{  
    string Create(Account account) 
    { 
     //Create account and return details 
    }; 

    void Update(Account account) 
    { 
     //Update account and return details 
    } 
    Account Get(string accountId); 
    { 
     //Return Account 
    } 
} 

E finalmente ecco l'errore che sto ottenendo nel mio test:

Castle.MicroKernel.Handlers.HandlerException: Impossibile creare il componente ' AccountRepositoryFeedEntryDecorator 'poiché ha dipendenze da soddisfare.

'AccountRepositoryFeedEntryDecorator' sta aspettando le seguenti dipendenze: - Component 'Shaw.Services.CustomerManagement.Host.Repositories.Sql.Decorators.AccountRepositoryAuthorizationDecorator' (via override) che è stato registrato, ma è anche in attesa di dipendenze.

'Shaw.Services.CustomerManagement.Host.Repositories.Sql.Decorators.AccountRepositoryAuthorizationDecorator' sta aspettando le seguenti dipendenze: - Servizio 'AccountRepositoryFeedEntryDecorator' che è stato registrato, ma è anche in attesa di dipendenze.

A prima vista sembra che ci sia una sorta di dipendenza circolare, ma non riesco davvero a vedere come.

Quindi la domanda in due parti, qual è la differenza tra le specifiche di dipendenza del componente e del servizio nel messaggio di errore, qualsiasi ipotesi su cosa stia succedendo.

Se è importante qui è la registrazione originale prima dell'aggiornamento:

RepositoryRegistration<IAccountRepository, AccountRepositoryFeedEntryDecorator>() 
    .ServiceOverrides(new { decoratedRepository = typeof(AccountRepositoryAuthorizationDecorator).Name }), 
RepositoryRegistration<AccountRepositoryAuthorizationDecorator>() 
    .ServiceOverrides(new { decoratedRepository = typeof(AccountRepositoryMaskingDecorator).Name }), 
RepositoryRegistration<AccountRepositoryMaskingDecorator>() 
    .ServiceOverrides(new { decoratedRepository = typeof(AccountRepository).Name }), 
RepositoryRegistration<AccountRepository>() 

risposta

6

registrazione Decorator si verifica in ordine di registrazione, e non è necessario specificare le dipendenze, quindi questo funzionerà come ci si aspetterebbe:

container.Register(
    RepositoryRegistration<IAccountRepository, AccountRepositoryFeedEntryDecorator>(), 
    RepositoryRegistration<IAccountRepository, AccountRepositoryAuthorizationDecorator>(), 
    RepositoryRegistration<IAccountRepository, AccountRepositoryMaskingDecorator>(), 
    RepositoryRegistration<IAccountRepository, AccountRepository>() 
); 

Risoluzione di un'istanza di IAccountRepository produrrà un AccountRepositoryFeedEntryDecorator, che decora un AccountRepositoryAuthorizationDecorator, etc.


Quanto alla tua domanda, this page fa un grande lavoro che spiega le differenze tra i servizi, i componenti e le dipendenze, come i termini vengono usati all'interno della libreria. In sostanza:

  • servizio è un po 'contratto di funzionalità, di solito un'interfaccia o delegato. È astratto
  • Il componente è un'implementazione di un servizio, in genere una classe. È concreto
  • Dipendenza è un servizio utilizzato da un componente.

Nel messaggio di errore, il primo bit è:

Castle.MicroKernel.Handlers.HandlerException: Impossibile creare il componente 'AccountRepositoryFeedEntryDecorator' quanto ha dipendenze per essere soddisfatti.

Ok, quindi la componente /classe non può essere creato perché le sue dipendenze non potevano essere soddisfatte. La sua dipendenza è il parametro IAccountRepository decoratedRepository nel costruttore.

'AccountRepositoryFeedEntryDecorator' sta aspettando le seguenti dipendenze: - Component 'AccountRepositoryAuthorizationDecorator' (via override) che è stato registrato, ma è anche in attesa di dipendenze.

Stiamo ancora parlando lo stesso componente/classe, e sta dicendo che stava cercando di utilizzare il componente/classe AccountRepositoryAuthorizationDecorator a svolgere la sua dipendenza, ma quella classe ha anche le dipendenze.

'AccountRepositoryAuthorizationDecorator' sta aspettando le seguenti dipendenze: - Servizio 'AccountRepositoryFeedEntryDecorator' che è stato registrato, ma è anche in attesa di dipendenze.

E siamo arrivati ​​alla prima classe, quindi c'è una dipendenza circolare. Questo a causa di una disconnessione tra il nome impostato in RepositoryRegistration e il nome calcolato quando si passa a un tipo su Dependency.OnComponent. Per il primo, si utilizza Type.Name (ad esempio, "AccountRepositoryFeedEntryDecorator"), e per quest'ultimo quest'ultimo utilizza Type.FullName sotto le copertine (ad esempio "Your.Assembly.Name, AccountRepositoryFeedEntryDecorator").

A causa della mancata corrispondenza dei nomi, quando Windsor tenta di soddisfare la dipendenza specificata, mancherà la registrazione perché ha un nome diverso. Di conseguenza, fa il meglio che può senza informazioni e (presumo) trova il primo IAccountRepository - che non è il componente stesso - può essere inserito come dipendenza. Questo accade di nuovo con quella dipendenza, che è il primo componente con cui abbiamo iniziato, dando una dipendenza circolare.

si potrebbe avere risolto questo rimuovendo la porzione Named della registrazione, o passando typeof(AccountRepositoryAuthorizationDecorator).Name a Dependency.OnComponent invece del tipo stesso.

+0

Ciao Patrick, ho appena provato questa soluzione, ma ora ricevo un errore che in primo luogo si lamenta che sta indicando il servizio, poi dice che ci sono altri componenti che corrispondono e continuano ad avere lo stesso problema di dipendenza "circolare". – Phaeze

+0

Riporto a prima vista sembra un problema di registrazione completamente diverso. – Phaeze

+0

@Phaeze Ah ok, beh se è collegato sentiti libero di aggiornare la tua domanda, altrimenti potrebbe avere senso come una nuova domanda del tutto. –

Problemi correlati