Casting,Generics和Subtypes

Tra*_*nus 5 c# generics

在尝试实现存储库模式时,我遇到了一个小问题,我担心其实会掩盖更大的问题.

我有一个DatabaseEntity <T>,我用它来处理所有基本的CRUD操作,并且需要存储在数据库中的所有其他类都将从中运行.它适用于直接从它继承的类,但是当它与具有中间父类的类一起使用时,我遇到了问题.

假设我有三个其他类,Parent,ChildA和ChildB,并且继承看起来像:

DatabaseEntity
          |
     家长
     | |
ChildA ChildB

还假设DatabaseEntity <T>具有带以下签名的方法:

public static T FindBy(int id)  
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是当我尝试这样的事情时:

ChildA Foo = ChildA.FindBy(SomeID);
Run Code Online (Sandbox Code Playgroud)

我收到编译器错误,告诉我没有从Parent到ChildA的隐式转换.这是因为Parent是将ChildA和ChildB的类型参数传递给DatabaseEntity的类.我认为简单的修复,只需向Parent添加一个类型参数,从而通过适当的类型.只需等待一秒钟,然后我必须在使用Parent时明确定义子类型,这会破坏任何多态性.不,第二个想法也许这不是一个很好的修复.

我认为我可以在类DatabaseEntity本身上删除type参数并让每个方法都需要一个类型参数但是我必须做类似的事情:

ChildA Foo = ChildA.FindBy<ChildA>(SomeID);
Run Code Online (Sandbox Code Playgroud)

虽然编译,但它似乎不太干净,当然需要更多打字.Visual Studio询问我是否错过了一个演员,而它的真实性我可以在我意外输入之前将我的第一个例子只是时间问题:

ChildB Foo = (ChildB) ChildA.FindBy(SomeID)
Run Code Online (Sandbox Code Playgroud)

我对目前为止我想到的任何解决方案都不是特别满意,我希望有人可以指出一个我错过的优雅解决方案.

Tom*_*cek 5

我认为制作Parent一个通用类是要走的路.您没有解释T示例中该类型的确切目的,但我想您希望它是实体的实际类型,因此例如您Parent将继承Entity<Parent>.

您仍然可以在此场景中编写多态代码 - 您只需使用泛型:

static void Foo<T>(Parent<T> p) where T : Parent<T>
{
  Parent<T> entity = p.Find();
}
Run Code Online (Sandbox Code Playgroud)

可以使用ChildA和调用此方法ChildB.唯一棘手的方面是你实际上不能创建一个实例Parent<Parent<...>>(因为点必须用更多的嵌套Parent<...>类型替换),但是你可以写下这样的东西:

class ParentFix : Parent<ParentFix> { }
Run Code Online (Sandbox Code Playgroud)

..然后你也可以传递ParentFixFoo方法的实例.