这个问题集中在依赖注入和通用接口上。
我的一个商业实体是身份证。可以有多种类型的身份证,均来自interface ICard
{
string CardId { get; }
}
class CardA : ICard
{
string CardId { get; set; }
string SomethingCardASpecific { get; set; }
}
class CardB : ICard
{
string CardId { get; set; }
bool SomethingCardBSpecific { get; set; }
}
:
CardFactory
我有一个ICard
,它会获取一张卡片ID并返回正确的卡片类型(class CardFactory : ICardFactory // Trivial interface definition left out
{
ICard FromCardId(string cardId)
{
if (MatchesPatternA(cardId))
{
return new CardA { CardId = cardId /* ... */ }
}
else
{
return new CardB { CardId = cardId /* ... */ }
}
}
}
):
interface ICardAuthorization<TCard> where TCard : ICard
{
bool IsOperationXPermitted(TCard card);
bool IsOperationYPermitted(TCard card);
}
此外,我还有另一个依赖项,用于检查卡是否有权执行某些操作。逻辑取决于卡类型,因此通用接口:
ICardFactory
我有一个依赖ICardAuthorization
和cardId
的API控制器。一个动作接收ICardAuthorization<ICard>
,创建一张卡,并检查它是否被授权执行操作X.控制器不关心两种卡类型的授权处理方式不同,因此它应该依赖于操作“基础”卡片类型(界面),即ICardAuthorization
。
实际问题:
当然,我至少需要class CardAAuthorization : ICardAuthorization<CardA> { /* ... */ }
class CardBAuthorization : ICardAuthorization<CardB> { /* ... */ }
的两种不同实现,即
ICard
但是,使用上述设计,API需要依赖于键入class DelegatingCardAuthorization : ICardAuthorization<ICard> { /* ... */ }
的接口:
ICardAuthorization<CardA>
反过来,这取决于两个“真正的”主力,ICardAuthorization<CardB>
和ICard
,并根据其方法接收的ICardAuthorization<TCard>
类型调用正确的主力。< / p>
当然,在我的应用程序中,resource: "@ProfileBundle/Rest/Xwsse/RestController.php"
to this like
resource: "@ProfileBundle/Resources/config/routing.yml"
只是需要针对不同卡类型实现不同实现的几个接口之一。
在我看来,这是一种相当强大的结构化方法,但我不喜欢这样的事实:我需要委托实现检查类型并将调用转发给其他实现。我可以忍受它,没问题,但有没有办法通过消除委托实现的需要来使这更优雅?(如果重要的话,我正在使用SimpleInjector。)
答案 0 :(得分:1)
我想你完全不需要委托实现,因为选择基于卡片类型的动作的逻辑应该存在于某个地方。
然而,我建议与工厂合作。
创建CardAuthorizationFactory
,它将根据传递给它的ICardAuthorization
对象的类型返回相应的ICard
实现者。为其他卡片操作创建任意数量的其他工厂。把所有这些作为单身人士放入IoC。
现在,当某些方法需要使用授权对卡执行某些操作时,它应该向AuthorizationFactory
查询适用于其当前卡对象的CardAuthorization
对象。工厂应该由IoC注入其中。它会满足您的需求吗?