I have a repository class that uses NPoco/PetaPoco to access data which reads from a common content table.
create table Content (
Id int not null identity primary key,
Type tinyint not null,
...
)
Then I have an abstract ContentBase
class that other types inherit. The main difference between inherited types being the value of that type DB column value. They do have some additional columns per concrete content type, but that's not relevant here.
So. In order for my repository class to return any of the actual concrete classes I wanted to write a medhod:
public TContent Create<TContent>(string name, ...)
{
...
// SP executes a few insers and returns newly created data instance
return db.Single<TContent>(
new Sql.Builder.Append(";exec dbo.CreateContent @Type, @Name, ...", new {
Type = TContent.Type, // this is the problem
Name = name,
...
}));
}
As you can see I would require my base abstract class to define a static member to get the actual type value that should be accessible through generic type specification. And inheriting classes should set it according to their concrete type implementation.
The problem is of course that there's no such thing as abstract static
members in C#.
How should I approach this problem in a way so that my repository will be able to provide Type
value on its own without me providing it explicitly with the call? I would only like to provide generic class when calling it and get back correct concrete type.
Why does it have to be static member?
My method doesn't get an object instance of a particular type but it should create one. That's why I can't really have an instance member Type
and read from that one while executing my repository method.
A possible start
As static members are shared among all instances and if this is base class all inheriting classes share the same member unless this class is generic. In that case we get a static member per generic type.
So I was thinking of adding an additional class between the base abstract and concrete classes:
public abstract class ContentBase
{
...
}
public abstract class ContentBase<TConcrete>
where TConcrete: ContentBase<ContentBase> // is this constraint ok?
{
public static ContentType Type = ???;
}
and then concrete classes:
public class ContentOne : ContentBase<ContentOne>
{
???
}
And as said I should be able to call my repository method as:
repo.Create<ContentOne>(name, ...)
where within this method repository should be able to access static member of generic type provided by the call...