In trying to implement the repository pattern I’ve run into a minor problem that I’m concerned actually belies bigger issues.
I’ve got a DatabaseEntity<T> which I’m using to handle all the basic CRUD operations and from which all other classes that need to be stored in a database will descend from. It is working fine for classes that inherit directly from it, however when using it with classes that have an intermediate parent I’ve run into a problem.
Suppose I have three other classes, Parent, ChildA and ChildB and and the inheritance looks like:
DatabaseEntity
|
Parent
| |
ChildA ChildB
Also suppose that DatabaseEntity<T> has a method with the following signature:
public static T FindBy(int id)
The issue I’m having is when I try something like:
ChildA Foo = ChildA.FindBy(SomeID);
I get a compiler error telling me that there’s no implicit conversion from a Parent to a ChildA. This is because Parent is the class that’s being passed in for the type parameter to DatabaseEntity for both ChildA and ChildB. Easy fix I think, just add a type parameter to Parent thus passing through the appropriate type. Only wait a second, then I’ll have to explicitly define the subtype any time I’m using Parent which ruins any polymorphism. No, on second thought maybe that’s not such a great fix.
I think that I could just drop the type parameter on the class DatabaseEntity itself and have each method require a type parameter but then I’d have to do something like:
ChildA Foo = ChildA.FindBy<ChildA>(SomeID);
While that compiles, it seems less clean and certainly requires more typing. Visual Studio asks if I’m missing a cast and while its true I could just cast my first example its only a matter of time before I accidentally type out:
ChildB Foo = (ChildB) ChildA.FindBy(SomeID)
I’m not especially pleased with any of the solutions I’ve thought of so far and I’m hoping someone here can point out an elegant one that I’ve missed.
I think that making
Parenta generic class is the way to go. You didn’t explain what exactly is the purpose of the typeTin your example, but I suppose you want it to be the actual type of the entity, so for example yourParentwould inheritEntity<Parent>.You can still write polymorphic code in this scenario – you just have to use generics:
This method can be called with both
ChildAandChildB. The only tricky aspect is that you cannot actually create an instance ofParent<Parent<...>>(because the dots would have to be replaced with more nestedParent<...>types), but you can write somthing like this:.. then you can pass instances of
ParentFixto theFoomethod as well.