根据基本通用类型调用正确的通用接口实现

问题描述:

该问题集中在依赖注入和通用接口上。根据基本通用类型调用正确的通用接口实现

我的一个商业实体是身份证。可以有多种类型的ID卡,全部来自ICard继承:

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,需要一个卡ID,并返回正确的卡类型(ICard):

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); 
} 

我有取决于ICardFactoryICardAuthorization一个API控制器。一个动作收到cardId,创建一张卡片,并检查它是否被授权采取行动X.控制器不关心两种卡片类型授权的处理方式不同,因此它应该取决于“基本”卡片上的操作类型(接口),即ICardAuthorization<ICard>

实际问题:

当然,我需要的ICardAuthorization至少两种不同的实现,即

class CardAAuthorization : ICardAuthorization<CardA> { /* ... */ } 
class CardBAuthorization : ICardAuthorization<CardB> { /* ... */ } 

然而,使用上述的设计中,API需要依赖的接口上输入到ICard

class DelegatingCardAuthorization : ICardAuthorization<ICard> { /* ... */ } 

这,反过来,d依靠两个“真正”的主力,ICardAuthorization<CardA>和​​,并根据其方法接收的ICard的类型调用正确的。

当然,在我的应用程序中,ICardAuthorization<TCard>只是需要针对不同卡类型实施不同卡的几种接口之一。

在我看来,这似乎是一种相当健壮的方式来构建事物,但我不喜欢这样一个事实,即我需要委托实现来检查类型并将调用转发给其他实现。我可以忍受它,没问题,但是否有任何方法通过消除委托实现的需要来使这更优雅?(我正在使用SimpleInjector,如果重要的话)。

+0

您可以详细介绍一张卡创建后会发生什么?它是否直接返回到web api客户端?还是进一步传递到某种业务层? –

+0

它不会返回给客户端,它仅用于业务层以识别用户。 – cmeeren

我想你不能完全删除委托实现的需要,因为选择基于卡类型的动作的逻辑应该驻留在某处。

然而,我提出的是与工厂同行。

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

现在,当某些方法需要使用授权对某张卡片进行操作时,它应该查询AuthorizationFactory以获取适合当前卡片对象的CardAuthorization对象。工厂应该由IoC注入。它会满足你的需求吗?

+0

谢谢!我看不出这对代表有什么好处。类的数量是相同的,这将需要一个更多的接口(用于工厂)。但谢谢你的建议。 :) – cmeeren

+0

@cmeeren至少我看到的一个好处是,工厂比习惯授权类更有名。 –

+1

当然,这是一个公平的观点。 – cmeeren