C# 使用泛型的新手多态性问题

C# 使用泛型的新手多态性问题,c#,generics,oop,polymorphism,C#,Generics,Oop,Polymorphism,我有下面的方法,它接收details对象,对其进行验证,将其转换为请求并将其排队。除了验证请求之外,一切都很好,我遇到了麻烦。基本上,每个不同的细节对象都有不同的验证逻辑。我从泛型约束知道details对象必须有一个BaseDetails基类,从实际的泛型参数知道确切的派生类型,但不知道如何使用这些来编写我的验证器类,以便它处理所有类型的详细信息: private void Enqueue<TDetails, TRequest>(TDetails details) wher

我有下面的方法,它接收details对象,对其进行验证,将其转换为请求并将其排队。除了验证请求之外,一切都很好,我遇到了麻烦。基本上,每个不同的细节对象都有不同的验证逻辑。我从泛型约束知道details对象必须有一个BaseDetails基类,从实际的泛型参数知道确切的派生类型,但不知道如何使用这些来编写我的验证器类,以便它处理所有类型的详细信息:

private void Enqueue<TDetails, TRequest>(TDetails details)  
   where TDetails: BaseDetails where TRequest: BaseRequest
{
  bool isValid = _validator.Validate(details);

  if (isValid)
  {
    TRequest request = ObjectMapper
      .CreateMappedMessage<TDetails, TRequest>(details);

    _queue.Enqueue(request);
  }
}
private void排队(详细信息)
where-TDetails:BaseDetails其中TRequest:BaseRequest
{
bool isValid=\u validator.Validate(详细信息);
如果(有效)
{
TRequest请求=ObjectMapper
.CreateMappedMessage(详细信息);
_排队(请求);
}
}

这只是意味着必须有一个相应的验证器层次结构,每个验证器都连接到自己的
t详细信息
对象。由于
TDetails
始终是
BaseDetails
,您需要手动指定支持哪个子类,并将执行链接到嵌套的验证器。

我认为您需要为TDetails的每个实现创建一个验证器类,它知道如何验证特定的实现,然后,让工厂为给定的TDetails实现生成正确的验证器,让您的_验证器从工厂获得正确的类来完成工作,并让类来完成验证

显然,您可以在基类中进行一些常见的验证


不过,您最好对对象本身进行验证,而不是为每个TDetails实现创建单独的验证器……

对我来说,验证逻辑应该附加到细节对象本身(当然,如果可能的话)。然后,您可以标记基类抽象,并在必要时覆盖特定细节类的
Validate
方法

另一方面,“组合重于继承”是目前的流行趋势

我从泛型约束中知道,details对象必须有一个BaseDetails基类

这在编译为字节码的过程中是已知的(我的意思是VisualStudio知道这一点)

从实际的泛型参数中,我知道了确切的派生类型

但这只有在JIT编译之后才知道(VisualStudio对此一无所知)。这就像是晚装

所以,如果您想用不同参数类型的多个方法编写一个验证器类,您不能这样做,因为VisualStudio编译器(在编译时)不知道将调用哪个方法

我相信没有办法跳过编写“switch(typeof(TDetails))”逻辑,其中验证器必须由TDetails选择。所以你必须写一些工厂,就像上面山姆·霍尔德写的


PS:对不起我的英语。我也在使用stackoverflow学习英语写作:)

您是否需要对每个TDetails实现进行不同的验证?是的,其中一些是常见的,但每个TDetails都有不同的额外位。这将是最简单的,但TDetails是WCF数据契约,我不允许触摸它们!然后,看起来每个TDetails都有一个验证器。让我们只希望您能够控制TDetails实现…@Stacey然后我将使用依赖项注入容器传递必要的验证器(特定于类的基本或派生细节)。与广泛接受的存储库模式类似。Re:工厂-如何定义?每个验证程序都会有一个不同的方法签名,因为它们将采用不同的类型,或者我会声明它们都采用基类,然后在每个验证方法中转换为派生类型吗?工厂会有一个方法
IDetailsValidator GetValidator(TDetails)
,然后执行
切换(typeof(TDetails))
然后针对每种情况返回该接口的实现。此接口将有一个方法
boolisvalid(TDetails)
。每个实现都将强制转换为方法中的正确类型并进行验证。您无法摆脱大开关(或if-then-else)构造,因此最好将其放在一个地方(factory类),在编写新的验证程序时可以在其中添加新的验证程序,而不必在代码中的多个位置执行检查。