基于基类泛型类型调用正确的通用接口实现

时间:2017-05-26 08:32:55

标签: c# dependency-injection simple-injector

这个问题集中在依赖注入和通用接口上。

我的一个商业实体是身份证。可以有多种类型的身份证,均来自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

我有一个依赖ICardAuthorizationcardId的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。)

1 个答案:

答案 0 :(得分:1)

我想你完全不需要委托实现,因为选择基于卡片类型的动作的逻辑应该存在于某个地方。

然而,我建议与工厂合作。

创建CardAuthorizationFactory,它将根据传递给它的ICardAuthorization对象的类型返回相应的ICard实现者​​。为其他卡片操作创建任意数量的其他工厂。把所有这些作为单身人士放入IoC。

现在,当某些方法需要使用授权对卡执行某些操作时,它应该向AuthorizationFactory查询适用于其当前卡对象的CardAuthorization对象。工厂应该由IoC注入其中。它会满足您的需求吗?