Casting,Generics和Subtypes

时间:2011-02-17 02:52:15

标签: c# generics

在尝试实施存储库模式时,我遇到了一个小问题,我担心这个问题实际上掩盖了更大的问题。

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

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

DatabaseEntity
|
家长
| |
                                     ChildA ChildB

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

public static T FindBy(int id)  

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

ChildA Foo = ChildA.FindBy(SomeID);

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

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

ChildA Foo = ChildA.FindBy<ChildA>(SomeID);

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

ChildB Foo = (ChildB) ChildA.FindBy(SomeID)

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

3 个答案:

答案 0 :(得分:5)

我认为让Parent成为一个通用类是可行的方法。您没有解释示例中T类型的目的究竟是什么,但我想您希望它是实体的实际类型,例如,您的Parent将继承{{} 1}}。

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

Entity<Parent>

可以使用static void Foo<T>(Parent<T> p) where T : Parent<T> { Parent<T> entity = p.Find(); } ChildA调用此方法。唯一棘手的方面是你实际上不能创建ChildB的实例(因为点必须用更多嵌套的Parent<Parent<...>>类型替换),但是你可以写这样的东西:

Parent<...>

..然后您也可以将class ParentFix : Parent<ParentFix> { } 的实例传递给ParentFix方法。

答案 1 :(得分:2)

我知道这不是您正在寻找的答案,但我建议使用一个现成的固态ORM,如Entity Framework 4.它支持开箱即用的继承,它是基本的,基本的用法存储库。

如果你试图自己动手,我认为你会遇到很多痛苦。

答案 2 :(得分:0)

我很抱歉,如果我没有在这里得到更大的图片,但你可以使DatabaseEntity<T>成为一个单独的通用类(可能是静态类),而不从中获取Parent。< /击>

<击>

这种安排允许使用DatabaseEntity<T>定义的所有CRUD操作和您可能拥有的任何类。

P.S。:如果我错过了一些明显的东西,请不要激怒我,我宁愿做一些澄清,以便我能更好地学习。