Here is my design of domain model and generic repository
public interface IEntity
{
long Id { get; }
}
public interface IRepository<T> where T : class, IEntity, new()
{
void Save(T entity);
void Delete(long id);
T Get(long id);
IEnumerable<T> GetAll();
}
public interface IUserRepository : IRepository<User>
{
User Login(string username, string password);
}
public class User : IEntity
{
// Implementation of User
}
public abstract class BaseRepository<T> : IRepository<T> where T : class, IEntity, new()
{
// Implementation of IRepository
}
public class UserRepository : BaseRepository<User>, IUserRepository
{
// Implementation of IUserRepository
// Override BaseRepository if required
}
When I want to instantiate a repository instance I use a factory which implements following interface
public interface IRepositoryFactory
{
R CreateRepository<R, T>()
where R : IRepository<T>
where T : class, IEntity, new();
}
And use the factory object as below
1. IRepositoryFactory factory = CreateFactory();
2. IUserRepository repository = factory.CreateRepository<IUserRepository, User>();
3. User user = repository.Login("user", "1234");
My problem is in the second line. I would like to use my factory like.
// Without specifying the User type parameter
factory.CreateRepository<IUserRepository>()
Since my IRepository interface has contstraint on type of entity my factory uses same constraint to satisfy IRepository requirement.
Is there any way to isolate this parameter from client?
I agree with the others that you would benefit from looking at a DI/IoC framework like Ninject.
So this answer is not a suggestion to not follow the other advices. But still, there are ways for you to solve your problem at a lower level. This code is not tested very well, but you could do something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using NUnit.Framework;
namespace TestConsole1
{
public interface IEntity
{
long Id { get; }
}
public interface IRepository<T> where T : class, IEntity, new()
{
void Save(T entity);
void Delete(long id);
T Get(long id);
IEnumerable<T> GetAll();
}
public interface IUserRepository : IRepository<User>
{
User Login(string username, string password);
}
public class User : IEntity
{
// Implementation of User
public long Id
{
get { return 42; }
}
}
public abstract class BaseRepository<T> : IRepository<T> where T : class, IEntity, new()
{
// Implementation of IRepository
public void Save(T entity)
{
throw new NotImplementedException();
}
public void Delete(long id)
{
throw new NotImplementedException();
}
public T Get(long id)
{
throw new NotImplementedException();
}
public IEnumerable<T> GetAll()
{
throw new NotImplementedException();
}
}
public class UserRepository : BaseRepository<User>, IUserRepository
{
// Implementation of IUserRepository
// Override BaseRepository if required
public User Login(string username, string password)
{
return new User();
}
}
class Factory
{
public T CreateRepository<T>() where T : class
{
//TODO: Implement some caching to avoid overhead of repeated reflection
var abstractType = typeof(T);
var types = AppDomain.CurrentDomain.GetAssemblies().ToList()
.SelectMany(s => s.GetTypes())
.Where(p => p.IsClass &&
!p.IsAbstract &&
abstractType.IsAssignableFrom(p));
var concreteType = types.FirstOrDefault();
if (concreteType == null)
throw new InvalidOperationException(String.Format("No implementation of {0} was found", abstractType));
return Activator.CreateInstance(concreteType) as T;
}
}
class Program
{
static void Main(string[] args)
{
var factory = new Factory();
var userRepo = factory.CreateRepository<IUserRepository>();
Console.WriteLine(userRepo.GetType());
User user = userRepo.Login("name", "pwd");
Console.WriteLine(user.Id);
Console.ReadKey();
}
}
}
As this code reveals, a central point is that you will need to handle the coupling between your interface and the concrete class, for example between your IUserRepository and your UserRepository. If you do not handle this relation in a direct way via a mapper or similar you can implement a more automatic way like the one that is illustrated in the code.
However, if you use something like Ninject instead to handle this for you, it will be a better investment of your time as you will most likely find that the complexity of your factory class will grow significantly over time.
Br. Morten
There are 3 problems with your code:
First is IEntity. Having single type of ID is against DDD, because in DDD, identity of object is given by domain and it can be anything from string, int, guid to complex type.
Second is generic repository with IRepository, which again, is highly useless, because you will rarely pass this interface and mostly will pass interface for repository for concrete entity.
Third thing is that in DDD repositories should exist only for aggregate roots, which is not reflected in your design.
If you fix this, you will find out, that implementation of interface of repository for specific entity can easily be suplied by DI framework.
Related
I am making a generic repository but for some entities I also need functionalities not provided by the generic repository. I have an interface IGenericRepository and concrete implementation as GenericRepository with basic CRUD operations. Further I have a studentRepository that uses the generic repository but also has functionalities of its own independent from the Generic Repository for which i have an Interface called IStudentRepository.
Here is the sample code:
public interface IGenericEntityRepository<T>
{
Delete(T entity);
T Get(int id);
IEnumerable<T> GetAll();
Add(T entity);
Update(T entity);
}
public class GenericEntityRepository<T> : IGenericEntityRepository<T> where T : class
{
protected readonly ApplicationDbContext _applicationDbContext;
public GenericEntityRepository(ApplicationDbContext applicationDbContext)
{
this._applicationDbContext = applicationDbContext;
}
//Generic Repository Implementations....
}
public interface IStudentRepository
{
string GetFullName(Student student)
double GetGpa(Student student)
}
public class StudentRepository: GenericRepository<Student>, IStudentRepository
{
public StudentRepository(ApplicationDbContext applicationDbContext) : base(applicationDbContext)
{}
//IStudentRepository functions' implementations...
}
Now I need to inject this StudentRepository to my StudentsController
public class StudentsController : Controller
{
private readonly IGenericEntityRepository<Student> _genericStudentRepository;
public StudentsController(IGenericEntityRepository<Student> _genericStudentRepository)
{
this._genericStudentRepository = genericRepository;
}
public void testAccessibility()
{
this._genericStudentRepository.GetAll() //valid call
this._genericStudentRepository.GetAllGpa() //invalid Call
***As expected cause IGenericEntityRepository doesn't have that ***function
}
}
As you can see the probelem here, if I inject IGenericEntityRepository I only get the genericrepository functionalities. If i want the functionalities of Student repository not included in genericRepository I have to inject both IGenericEntityRepository and IStudentRepository like below and vice versa.
public class StudentsController : Controller
{
private readonly IGenericEntityRepository<Student> _genericStudentRepository;
private readonly IStudentRepository _studentsRepository;
public StudentsController(IGenericEntityRepository<Student> _genericStudentRepository, IStudentRepository studentsRepository)
{
this._genericStudentRepository = genericRepository;
this.__studentsRepository = studentsRepository;
}
public void testAccessibility()
{
this._genericStudentRepository.GetAll() //valid call
this._studentsRepository.GetAllGpa() //valid call
}
}
Is there a better way to do this? Doesn't feel right injecting two contextually same but coding wise different objects like this.
You can have IStudentRepository extend IGenericEntityRepository<T>:
public interface IStudentRepository : IGenericEntityRepository<Student>
{
string GetFullName(Student student)
double GetGpa(Student student)
}
Now injecting IStudentRepository should be enough to use all the functions.
So I'm following a tutorial about dependency injection with Unity in C#. In the tutorial, they used repository classes as an example to demonstrate the concept. Trying to apply that to one of sample projects, I encountered an inheritance problem. So I have
public interface IRepository<T> where T : class
{
List<T> GetAll();
T Get(int id);
void Add(T entity);
void SaveChanges();
}
public class Repository<T> : IRepository<T> where T : class
{
private CoffeeMachineDbContext context = null;
protected virtual DbSet<T> DbSet { get; set; }
public Repository()
{
context = new CoffeeMachineDbContext();
DbSet = context.Set<T>();
}
public Repository(CoffeeMachineDbContext context)
{
this.context = context;
}
public virtual List<T> GetAll()
{
return DbSet.ToList();
}
public virtual T Get(int id)
{
return DbSet.Find(id);
}
public virtual void Add(T entity)
{
DbSet.Add(entity);
}
public void SaveChanges()
{
context.SaveChanges();
}
}
The repository class implements the interface and the common methods.
Now To be able to apply dependency injection as it was explained (or at least as I understood it), I created a new interface named IClientRepository that inherits from IRepository as follow:
public interface IClientRepository : IRepository<Client>
{
Order GetLastOrder(int id);
}
Notice that the interface declares a new method that it's specific to clients context.
Finally, the implementation of the IClientRepository interface is:
public class ClientRepository : Repository<Client>, IClientRepository
{
/// <summary>
/// Gets the client's last order
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public Order GetLastOrder(int id)
{
Order lastOrder = null;
Client client = DbSet.Find(id);
if (client != null)
{
lastOrder = client.Orders.OrderByDescending(o => o.DateCreated).FirstOrDefault();
}
return lastOrder;
}
I don't need to implement the IRepository methods because they are common between all others.
The issue that I'm facing is that when I'm trying to register type in the unity container as follow:
container.RegisterType<IClientRepository, ClientRepository>(new HierarchicalLifetimeManager());
I get the following error
The type 'CoffeeMachine.Models.Repositories.ClientRepository' cannot be used as type parameter 'TTo' in the generic type or method 'UnityContainerExtensions.RegisterType(IUnityContainer, LifetimeManager, params InjectionMember[])'. There is no implicit reference conversion from 'CoffeeMachine.Models.Repositories.ClientRepository' to 'CoffeeMachine.Models.Repositories.IClientRepository'.
Does anyone have any idea what I did wrong here?
That error happens because your class doesn't actually implement IClientRepository.
You can only cast an instance to an interface if its class actually implements that interface.
I hv two entities, USER and Document. both have their own interface Iuser and I Document.
public class UserRepository : IUserRepository<UserRepository>
{
public string GetUser()
{
return "Akash";
}
}
public interface IUserRepository<T> : IRepository<T> where T : class
{
string GetUser();
}
public class DocumentRepository : IDocumentRepository<DocumentRepository>
{
public string GetDocument()
{
return "Akash";
}
}
public interface IDocumentRepository<T> : IRepository<T> where T : class
{
string GetDocument();
}
Below is the base interface. All repo interfaces implement this base interface. It is empty ( on purpose) as I just want to store all repo class object in this IRepository interface variable.
public interface IRepository<T> where T : class
{
}
and than, in my UOW ( unit of work ) class, I am creating the repo instance as follows,
public IRepository<UserRepository> UserProfile
{
get
{
return GetRepository<UserRepository>();
}
}
private IRepository<T> GetRepository<T>() where T : class, new()
{
return (IRepository<T>)new T();
}
Now the problem is: repo object does not have the methods implemented in each repo class. It is obvious as I am type casting my repo object with IRepository interface which does not have any methods. I am looking for a work around. my purpose is to store all repo object in IRepository variable. Kindly suggest. This is typical OOP's issue.
I have a base repository contract which other contracts extend, like follows
public interface IBaseRepository<T> where T : class
{
IList<T> GetContents();
}
and then there are other contracts which extend it like follows
public interface IRepository1 : IBaseRepository<MyClass1>
{
}
public interface IRepository2 : IBaseRepository<MyClass2>
{
}
I implement IRepository1 as follows
public class Repository1 : IRepository1
{
public IList<MyClass1> GetContents()
{
//some code goes here
}
}
similarly for IRepository2
public class Repository2 : IRepository2
{
public IList<MyClass2> GetContents()
{
//some code goes here
}
}
Now i have a service Service1 which implments IService like follows
public class Service1 : IService
{
}
I want to use my base repository (IBaseRepository) here in my service constructor, get an instance of this base repository and use it like so
public class Service1 : IService
{
private IBaseRepository<T> _baseRepository;
public Service1(IBaseRepository<T> baseRepository)
{
_baseRepository = baseRepository;
}
public MyMethod1()
{
var contentsOfType1 = _baseRepository<MyClass1>.GetContents();
}
public MyMethod1()
{
var contentsOfType2 = _baseRepository<MyClass2>.GetContents();
}
}
and this is what i am unable to do.
So i have a generic base repository contract with type T and have other contracts (interfaces) extending the base contract and also specifying what type T will be.
All these contracts (which extend generic base contract) have thier individual implementations.
What i want to do is in my service class, instantiate this generic base contract, and use it to infer the extending types (and hence implementations) and use the method from the base repository.
So if the base contract is
IBaseRepository<T>
and extending contract is
IRepository1 : IBaseRepository<MyClass1>
which is implemented by
Repository1 : IRepository1
i want to use this in my service class like
public class service()
{
*private IBaseRepository<T> _repo;
public service(IBaseRepository<T> repo)
{
*_repo = repo;
}
public void MyMethod()
{
*var x = _repo<MyClass1>.MethodFromIBaseRepository()
}
}
So its the *marked lines i want to achieve, which i am unable to.
I am using castle windsor for DI.
Thanks for your help guys
You should not have other repository interfaces besides your generic IRepository<T>. If you need those, you are missing an abstraction.
For instance, a common reason for people to have custom repository interfaces is because they have a custom query that some repository has, while other don't. For instance:
public interface IEmployeeRepository : IRepository<Employee>
{
Employee GetEmployeeOfTheMonth(int month);
}
The problem here is that the IEmployeeRepository is abused for a 'custom query'. Custom queries deserve their own (generic) abstraction:
// Defines a query
public interface IQuery<TResult>
{
}
// Defines the handler that will execute queries
public interface IQueryHandler<TQuery, TResult>
where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
With this abstraction we can add custom queries to the system, without the need of creating IRepository<T> derivatives:
public class GetEmployeeOfTheMonthQuery : IQuery<Employee>
{
[Range(1, 12)]
public int Month { get; set; }
}
class GetEmployeeOfTheMonthHandler : IQueryHandler<GetEmployeeOfTheMonthQuery, Employee>
{
public Employee Handle(GetEmployeeOfTheMonthQuery query)
{
// todo: query the database, web service, disk, what ever.
}
}
A consumer that needs to know the employee of the month, can now simply take a dependency on IQueryHandler<GetEmployeeOfTheMonthQuery, Employee> and execute the query as follows:
var query = new GetEmployeeOfTheMonthQuery { Month = 11 };
var employee = this.employeeOfMonthHandler.Handle(query);
This might seem like overhead, but this model is very flexible, scalable, and has many interesting benefits. For instance, it is very easy to add cross-cutting concerns by wrapping handlers with decorators.
This also allows our reposities to be hidden behind one generic interface, which allows us to easily batch register them at once and add decorators to them as well.
For more in depth information, read this article: Meanwhile… on the query side of my architecture.
Not possible. The inversion of control container provide dependencies through the constructor, hence it must know in the constructor what type you want to get. So you should do this:
public class service()
{
private IBaseRepository<MyClass1> _repo;
public service(IBaseRepository<MyClass1> repo)
{
_repo = repo;
}
public void MyMethod()
{
var x = _repo.MethodFromIBaseRepository()
}
}
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;}
}
Try this;
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> : IRepository<T> where V : EmployeeRepo where T : class
{
void DoSomethingEmployeeRelated();
}
//Dont think this inheritance is correct
public class EmployeeRepo : IEmployeeRepo<Employee, EmployeeRepo>
{
public void DoSomethingEmployeeRelated()
{
}
public void GetAllData<Employee>()
{
}
}
//My example model class
public class Employee
{
public string Name {get;set;}
}