组件和服务依赖项之间有什么区别?

Jus*_*ica 6 c# castle-windsor

我将在声明前面提出这个问题:我知道以下是糟糕的设计,但重构目前不是一个选项,理想情况下应该使用拦截器完成.

我正在努力将城堡从1.6(我认为)升级到3.3,遗憾的是它涉及一些语法更改,我现在已经编译了所有内容,但我在服务容器周围的一些测试无法正常工作.

我有一个存储库,它有几个实现来提供不同的功能,存储库只与内联的所有不同实现一起使用,以下是代码的基础知识:

温莎城堡注册:

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>());
Run Code Online (Sandbox Code Playgroud)

RepositoryRegistration方法:

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

基础接口:

public interface IAccountRepository
{
    string Create(Account account);
    void Update(Account account);
    Account Get(string accountId);
}
Run Code Online (Sandbox Code Playgroud)

实施:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

最后这是我在测试中得到的错误:

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>()
Run Code Online (Sandbox Code Playgroud)

Pat*_*irk 7

装饰器注册按注册顺序进行,您无需指定依赖项,因此这将按您的预期工作:

container.Register(
    RepositoryRegistration<IAccountRepository, AccountRepositoryFeedEntryDecorator>(),
    RepositoryRegistration<IAccountRepository, AccountRepositoryAuthorizationDecorator>(),
    RepositoryRegistration<IAccountRepository, AccountRepositoryMaskingDecorator>(),
    RepositoryRegistration<IAccountRepository, AccountRepository>()
);
Run Code Online (Sandbox Code Playgroud)

解析一个实例IAccountRepository将产生一个AccountRepositoryFeedEntryDecorator,装饰一个AccountRepositoryAuthorizationDecorator,等等.


至于您的问题,此页面可以很好地解释服务,组件和依赖关系之间的差异,因为术语在库中使用.实质上:

  • 服务是一些功能合同,通常是接口或委托.这是抽象的.
  • 组件是服务的实现,通常是类.这是具体的.
  • 依赖关系是组件使用的服务.

在您的错误消息中,第一位是:

Castle.MicroKernel.Handlers.HandlerException:无法创建组件'AccountRepositoryFeedEntryDecorator',因为它具有要满足的依赖项.

好的,因此无法创建组件/类,因为无法满足其依赖性.它的依赖项是IAccountRepository decoratedRepository构造函数中的参数.

'AccountRepositoryFeedEntryDecorator'正在等待以下依赖项: - 已注册但仍在等待依赖项的组件'AccountRepositoryAuthorizationDecorator'(通过覆盖).

我们仍然在讨论相同的组件/类,并且它说它正在尝试使用组件/类AccountRepositoryAuthorizationDecorator来实现其依赖性,但该类也具有依赖性.

'AccountRepositoryAuthorizationDecorator'正在等待以下依赖项: - 已注册但仍在等待依赖项的服务'AccountRepositoryFeedEntryDecorator'.

而且我们已经到了第一类,所以存在循环依赖.这是因为设置的名称RepositoryRegistration与传入类型时计算的名称之间的断开连接Dependency.OnComponent.对于前者,您正在使用Type.Name(即"AccountRepositoryFeedEntryDecorator"),而后者使用Windsor Type.FullName(即"Your.Assembly.Name,AccountRepositoryFeedEntryDecorator").

由于命名不匹配,当Windsor尝试实现您指定的依赖项时,它将错过其注册,因为它具有不同的名称.因此,它可以在没有信息的情况下做到最好,并且(我假设)找到第一个IAccountRepository- 它不是组件本身 - 它可以作为依赖项插入.这种依赖性再次发生,这是我们开始的第一个组件,给出了循环依赖.

您可以通过删除Named注册部分或通过传递而不是类型本身typeof(AccountRepositoryAuthorizationDecorator).Name来解决这个问题Dependency.OnComponent.