我将在声明前加上这个问题:我知道以下是糟糕的设计,但重构目前不是一个选项,理想情况下应该使用拦截器完成。
我正在努力将城堡从1.6(我认为)升级到3.3,遗憾的是它涉及一些语法更改,我现在已经编译了所有内容,但我对服务容器的一些测试无效。
我有一个存储库,它有几个实现来提供不同的功能,存储库只与内联的所有不同实现一起使用,这里是代码的基础:
Castle Windsor注册:
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>());
RepositoryRegistration方法:
private static ComponentRegistration<TRepository> RepositoryRegistration<TRepository, TConcreteRepository>()
where TConcreteRepository : TRepository where TRepository : class
{
return Component
.For<TRepository>()
.ImplementedBy<TConcreteRepository>()
.Named(typeof(TConcreteRepository).Name);
}
基础界面:
public interface IAccountRepository
{
string Create(Account account);
void Update(Account account);
Account Get(string accountId);
}
实施:
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
}
}
最后这是我在测试中遇到的错误:
Castle.MicroKernel.Handlers.HandlerException:无法创建组件'AccountRepositoryFeedEntryDecorator',因为它具有要满足的依赖项。
'AccountRepositoryFeedEntryDecorator'正在等待以下依赖项: - 组件'Shaw.Services.CustomerManagement.Host.Repositories.Sql.Decorators.AccountRepositoryAuthorizationDecorator'(通过覆盖)已注册,但也在等待依赖。
'Shaw.Services.CustomerManagement.Host.Repositories.Sql.Decorators.AccountRepositoryAuthorizationDecorator'正在等待以下依赖项: - 服务'AccountRepositoryFeedEntryDecorator'已注册,但也在等待依赖。
乍一看似乎发生了某种循环依赖,但我真的看不出来。
所以问题分为两部分,错误信息中组件和服务依赖规范之间的区别是什么,对错误的猜测是什么。
如果重要的是升级前的原始注册:
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>()
答案 0 :(得分:7)
装饰器注册按注册顺序进行,并且您不需要指定依赖项,因此这将按照您的预期运行:
container.Register(
RepositoryRegistration<IAccountRepository, AccountRepositoryFeedEntryDecorator>(),
RepositoryRegistration<IAccountRepository, AccountRepositoryAuthorizationDecorator>(),
RepositoryRegistration<IAccountRepository, AccountRepositoryMaskingDecorator>(),
RepositoryRegistration<IAccountRepository, AccountRepository>()
);
解析IAccountRepository
的实例会产生AccountRepositoryFeedEntryDecorator
,它会装饰AccountRepositoryAuthorizationDecorator
等。
关于你的问题,this page很好地解释了服务,组件和依赖关系之间的差异,因为术语在库中使用。基本上:
在您的错误消息中,第一位是:
Castle.MicroKernel.Handlers.HandlerException:无法创建组件'AccountRepositoryFeedEntryDecorator',因为它具有要满足的依赖项。
好的,因此无法创建组件 / 类,因为无法满足依赖项。它的依赖项是构造函数中的IAccountRepository decoratedRepository
参数。
'AccountRepositoryFeedEntryDecorator'正在等待以下依赖项: - 已注册但仍在等待依赖项的组件'AccountRepositoryAuthorizationDecorator'(通过覆盖)。
我们仍然在谈论相同的组件/类,并且它说它正在尝试使用组件/类AccountRepositoryAuthorizationDecorator
来实现其依赖性,但该类也具有依赖性。
'AccountRepositoryAuthorizationDecorator'正在等待以下依赖项: - 服务'AccountRepositoryFeedEntryDecorator'已注册,但也在等待依赖项。
我们已经到了第一堂课,所以有一个循环依赖。这是因为RepositoryRegistration
中设置的名称与将类型传递给Dependency.OnComponent
时计算的名称之间的断开连接。对于前者,您使用Type.Name
(即“AccountRepositoryFeedEntryDecorator”),而后者使用Type.FullName
封面(即“Your.Assembly.Name,AccountRepositoryFeedEntryDecorator”)。
由于命名不匹配,当Windsor尝试实现您指定的依赖项时,它将错过其注册,因为它具有不同的名称。因此,它可以在没有信息的情况下做到最好,并且(我假设)找到第一个IAccountRepository
- 这不是组件本身 - 它可以作为依赖项插入。这种依赖性再次发生,这是我们开始的第一个组件,给出了循环依赖。
您可以通过删除注册的Named
部分,或将typeof(AccountRepositoryAuthorizationDecorator).Name
传递给Dependency.OnComponent
而不是类型本身来解决此问题。