Consider this example:
Database (similar to Stackoverflow) has a table with questions and answers in the same table distinguishable by PostType
field. I would like to get back a list of lastest posts be it questions or answers.
As questions and answers share common properties, both classes inherit from an abstract class ContentBase
. They only add few additional fields that are relevant for each type.
How do I get a list of content items cast to IList<ContentBase>
while individual items are of a concrete type Question
or Answer
based on the criteria field.
public abstract class ContentBase
{
public int Id { get; set; }
public string Title { get; set; }
public User Author { get; set; }
public abstract ContentType Type { get; }
...
}
public class Question : ContentBase
{
public override ContentType Type
{
get { return ContentType.Question; }
}
...
}
public class Answer: ContentBase
{
public override ContentType Type
{
get { return ContentType.Answer; }
}
...
}
My repository would then have a call:
IList<ContentBase> result = db.GetLatest();
I'm using PetaPoco/NPoco, but I suppose the same problem would arise if one would use Dapper.
Question
How does one instruct DAL to instantiate correct concrete types based on particular field's value (ContentType
in this case)?
Explanation
I should be doing something along these lines:
db.Fetch<ContentBase, User>(...)
But I can't because ContentBase
is an abstract class. If I change this line to:
db.Fetch<dynamic, User>(...)
it still won't work, because I get an InvalidOperationException
from NPoco saying Can't auto join User.
I suppose the only way to do this is to create a new class inherited from PocoData
and provide my own implementation of GetFactory
delegate. I think. I don't think there's any other extensibility point where concrete POCOs get instantiated and I'm not sure whether I should do it this way and how since I'm handling abstract ancestor class.