I'm going to preface this question with the statement: I know the following is bad design, but refactoring is not currently an option, ideally it should be done using interceptors.
I am working on upgrading castle from 1.6 (I think) to 3.3 which unfortunately involves some syntax changes, I've got everything compiling now but some of my tests around the service container aren't working.
I have a repository that has several implementations to provide different functionality, the repository is only ever used with all of the different implementations inline, here are the basics of the code:
The Castle Windsor registrations:
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>());
The RepositoryRegistration method:
private static ComponentRegistration<TRepository> RepositoryRegistration<TRepository, TConcreteRepository>()
where TConcreteRepository : TRepository where TRepository : class
{
return Component
.For<TRepository>()
.ImplementedBy<TConcreteRepository>()
.Named(typeof(TConcreteRepository).Name);
}
The base interface:
public interface IAccountRepository
{
string Create(Account account);
void Update(Account account);
Account Get(string accountId);
}
The implementations:
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
}
}
And finally here is the error I'm getting in my test:
Castle.MicroKernel.Handlers.HandlerException : Can't create component 'AccountRepositoryFeedEntryDecorator' as it has dependencies to be satisfied.
'AccountRepositoryFeedEntryDecorator' is waiting for the following dependencies: - Component 'Shaw.Services.CustomerManagement.Host.Repositories.Sql.Decorators.AccountRepositoryAuthorizationDecorator' (via override) which was registered but is also waiting for dependencies.
'Shaw.Services.CustomerManagement.Host.Repositories.Sql.Decorators.AccountRepositoryAuthorizationDecorator' is waiting for the following dependencies: - Service 'AccountRepositoryFeedEntryDecorator' which was registered but is also waiting for dependencies.
At first glance it appears there is some kind of circular dependency happening, but I can't really see how.
So the question in two parts, what is the difference between the component and service dependency specifications in the error message, any guesses as to what is going wrong.
If it matters here is the original registration before the upgrade:
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>()