I have read a bit about constraints and am trying to implement it in my repository pattern.
I want something like the below but can't quite get it to compile.
public interface IRepository<T>
{
void GetAllData<T>();
}
//This needs to inherit from IRepository
//T has to be a model class
//V has to be a class that implements IEmployeeRepo
public interface IEmployeeRepo<T, V> where V : EmployeeRepo where T : class : IRepository<T>
{
void DoSomethingEmployeeRelated();
}
//Dont think this inheritance is correct
public class EmployeeRepo<Employee, this> : IEmployeeRepo
{
}
//My example model class
public class Employee
{
public string Name {get;set;}
}
Not sure why you have two type parameters on the Repository - what is the point?
*Here is the classic example of a .NET Repository using Generics: *
*First, the Repository Interface: *
public interface IRepository<T> where T : class
{
T FindSingle(Expression<Func<T,bool>> predicate);
IQueryable<T> FindAll(); // optional - matter of preference
void Add(T entity);
void Remove(T entity);
}
*Second, the Generic Repository Implementation (EF as the example): *
public abstract class GenericRepository<T> : IRepository<T>
{
private IObjectSet<T> _ObjectSet; // get this in via DI (for example)
public T FindSingle(Expression<T,bool>> predicate)
{
return _ObjectSet.SingleOrDefault(predicate);
}
// you can figure out how to do the other implementation methods
}
*Then, the Specific Repository (you should have one per aggregate root, and also an interface for each specific repository detailing specific methods): *
public EmployeeRepository : GenericRepository<Employee>, IRepository<Employee>
{
// all regular methods (Find, Add, Remove) inherited - make use of them
public Employee FindEmployeeByName(string name)
{
return FindAll().SingleOrDefault(x => x.Name == name);
// or you could do: return FindSingle(x => x.Name == name);
}
}
Usage:
IRepository<Employee> repository = new EmployeeRepository<Employee>();
Don't go out looking to go too crazy with generics - the only one you need is to constrain the Repository to be used by a entity that is encapsulated behind the Repository.
I simply use where T : class
.
Other's use where T : IDomainAggregate
or similar, to put constraints on the actual type of entity which is allowed.
In this situation i usually have a base repo class that implements IRepository<>, and is typed to a base Model class.
public interface IRepository<T> where T : IModel
{
void GetAll<T>();
void GetById<T>(int id);
}
public interface IEmployeeRepo<T> : IRepository<T> where T : IModel
{
void DoSomethingEmployeeRelated();
}
public class BaseRepo : IRepository<T> where T : IModel
{
public void GetAll<T>()
{
}
public void GetById<T>(int id)
{
}
}
public class EmployeeRepo : BaseRepo<Employee>, IEmployeeRepo<Employee>
{
public void DoSomethingEmployeeRelated()
{
}
}
//My example model class
public class Employee : IModel
{
public int Id {get;set;}
public string Name {get;set;}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With