I am trying to become a good programming citizen through learning more about Dependency Injection / IoC and other best-practices methods. For this I have a project where I am trying to make the right choices and design everything in the "proper" way, whatever that might mean. Ninject, Moq and ASP.NET MVC help with testability and getting the app "out the door".
However, I have a question about how to design an entity base class for the objects that my application consists of. I have a simple class library which the web app is built on top of. This library exposes a IRepository interface, and the default implementation (the one that the app uses) uses Linq-to-SQL under the covers (the DataContext etc. is not exposed to the web app) and simply contains ways to fetch these entities. The repository basically looks like this (simplified):
public interface IRepository
{
IEnumerable<T> FindAll<T>() where T : Entity
T Get<T>(int id) where T : Entity
}
The default implementation uses the GetTable() method on the DataContext to provide the correct data.
However, this requires that the base class "Entity" has some features. It is easy enough to get my objects to inherit from it by creating a partial class of the same name as the mapped object that Linq-to-SQL gives me, but what is the "correct" way to do this?
For instance, the interface above has a function for getting an Entity by it's id - all the different kinds of classes that derives from entity does indeed have an "id" field of type int (mapped from the primary key of their respective tables), but how can I specify this in a way that lets me implement IRepository like this?
public class ConcreteRepository : IRepository
{
private SomeDataContext db = new SomeDataContext();
public IEnumerable<T> FindAll<T>() where T : Entity
{
return db.GetTable<T>().ToList();
}
public T Get(int id) where T : Entity
{
return db.GetTable<T>().Where(ent => ent.id == id).FirstOrDefault();
}
}
I am doing this from memory on a compiler-less PC so forgive any errors, you hopefully get my intention.
The trick here is of course that for this to compile, it has to be known for sure that Entity promises that everyone that derives from it has an id field.
And I can make an abstract field, or a normal field that is "hidden" by the id field that Linq-to-SQL sticks in the generated classes.
But this all feels kind of like a cheat, and even gives compiler warnings.
Should "Entity" really be "IEntity" (an interface instead), and I should try to make the id field be defined in a way that Linq-to-SQL will fulfill? This would also make it easy to specify other interfaces that Entity-implementors need to implement.
Or should "Entity" be an abstract base class with an abstract id field, and should it also implement needed interfaces in an abstract way for others to override?
I don't know C# well enough to see an elegant solution to this, so I would love to hear from more experienced system designers with some base class experience weigh in on this.
Thanks!
EDIT April 10th:
I see I left out something important here. My IRepository has two concrete implementations - one that is the "real" one using LINQ to SQL, the other one is a InMemoryRepository that just uses a List for now, which is used for unit testing etc.
The two solutions added will both work for one of these situations, not for the other. So if possible, I would need a way to define that everything that inherits from Entity will have the "id" property, and that this will work with the LINQ to SQL DataContext without "cheating".