I need some help with the design of the Unit of Work + Repository + IoC pattern. I have several interfaces defined as follows:
public interface IRepository<T>
{
T GetEntity(int id);
}
public interface IUserRepository : IRepository<User>
{
User GetUserByXyz(int id);
}
public interface IUnitOfWork
{
T Respository<T>() where T : IRepository<T>;
}
I am using Unity to resolve some references. Here's the implementation of the UoW:
public class UnitOfWork : IUnitOfWork
{
public T Respository<T>() where T : IRepository<T>
{
var container = new UnityContainer();
return container.Resolve<T>();
}
}
Now i am having trouble calling the interface:
User user = _unitOfWork.Respository<IUserRepository>().GetUserByXyz(1);
The type 'IUserRepository' cannot be used as type parameter 'T' in
the generic type or method 'IUnitOfWork.Respository()'. There is no
implicit reference conversion from 'IUserRepository' to
'IRepository'.
How do get around the generic constraint error?
Expanding on my comment:
The statement public T Respository<T>() where T : IRepository<T> implies that you're expecting a type that is a Repository of itself, e.g. IUserRepository would have to be an IRepository<IUserRepository> to satisfy your condition.
You need two different generics, one for the item that is held in the reporsitory TItem and another for the repository itself, TRepo.
Then the whole code becomes:
public interface IRepository<TItem>
{
TItem GetEntity(int id);
}
public interface IUserRepository : IRepository<User>
{
}
public interface IUnitOfWork
{
TRepo Respository<TRepo,TItem>() where TRepo : IRepository<TItm>;
}
and
public class UnitOfWork : IUnitOfWork
{
public TRepo Respository<TRepo,TItem>() where TRepo : IRepository<TItem>
{
var container = new UnityContainer();
return container.Resolve<TRepo>();
}
}
finally, the call becomes:
User user = _unitOfWork.Respository<IUserRepository,User>().GetEntity(1);
Initial note:
_unitOfWork.Respository<IUserRepository>()…
As it is, you're essentially "abusing" UnityOfWork as a service locator (you can ask it for any type of repository), but it doesn't seem to offer any additional benefits. Is this really what you want? Couldn't you just do away with UnitOfWork and do the following instead:
_unityContainer.Resolve<IUserRepository>()…
Alternative solution that does not require a second type parameter:
I agree with #Jon Egerton that for this to work correctly, one option would be to introduce a second generic type parameter (TItem next to TItemRepository). There is, however, another solution involving a marker interface IRepository:
// non-generic marker interface (empty)
public interface IRepository {}
public interface IRepository<T> : IRepository { … /* as before */ }
// ^^^^^^^^^^^^^
// added
public class UnitOfWork
{
public TRepository Get<TRepository>() where TRepository : IRepository
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// this way, no 2nd type parameter is
// needed since the marker interface is
// non-generic.
{
return new UnityContainer().Resolve<TRespository>();
}
}
As requested: Unit of Work example:
If you follow Martin Fowler's definition for the Unit of Work pattern, you get something rather different from what you've got right now. Rather, a Unit of Work according to his udnerstanding merely keeps track of all changes that have been made to a collection of objects. The idea behind this is that changes aren't persisted (e.g. to a database) one at a time, but all at the same time, when requested through the unit of work object; thus the pattern's name:
class UnitOfWork<T>
{
// the UnitOfWork object tracks changes to objects of type T:
private HashSet<T> newItems;
private HashSet<T> modifiedItems;
private HashSet<T> removedItems;
public void Commit()
{
// let's say items are persisted to an RDBMS, then:
// * generate 'DELETE FROM [tableForItemsOfTypeT]' statements
// for all items in the 'removedItems' set;
// * generate 'INSERT INTO [tableForItemsOfTypeT]' statements
// for all items in the 'newItems' set;
// * generate 'UPDATE [tableForItemsOfTypeT]' statements
// for all items in the 'modifiedItems' set.
}
}
Your definition of IUnitOfWork seems a little peculiar, and it seems you've got your generic parameter constraint wrong:
public interface IUnitOfWork
{
T Respository<T>() where T : IRepository<T>;
}
I'd try to get rid of the generic parameter constraint, if possible. For example:
public interface IUnitOfWork<T>
{
IRepository<T> Respository { get; }
}
public class UnitOfWork<T> : IUnitOfWork<T>
{
public IRepository<T> Respository
{
get
{
var container = new UnityContainer();
return container.Resolve<IRepository<T>>();
}
}
}
(Admittedly, I'm not sure whether it's a good idea to constrain a UnitOfWork class to one particular object type by parameterizing it this way. You could in theory also have a UnitOfWork class that implements IUnitOfWork<T> several times, for different T, though that's probably equally unwise. Judge yourself what is most appropriate for your purposes.)
Note that you'd then also have to register your types differently. You could possibly also get rid of IUserRepository this way.
P.S.: Probably, Repository does make more sense if it's a method, and not a property, as shown above. I'd choose based on how costly it is to "get" a repository. If it's expensive, make it a method; if it's a cheap operation, a property might be just fine. If you keep it as a method, I'd rename it to GetRepository to better adhere to the common .NET naming guidelines. Alternative approach:
public interface IUnitOfWork
{
IRepository<T> GetRespository<T>()
}
You are confusing your Generic constraint:
public T Respository<T,U>() where T : IRepository<U>
User user = _unitOfWork.Respository<IUserRepository,User>().GetEntity(1);
Related
We have an interface to deal with DAL with pretty simple definition:
interface IRepository<T> : IQueriable<T> // so we can read data from database
{
Save(T document); // dozen of methods here
}
Mostly we use two implementations: real version and in memory version for unit testing. Here is declarations of one of class:
public RealRepository : IRepository<AccountEntity> { ... }
// typical IOC usage
services.AddSingleton<IRepository<AccountEntity>, RealRepository<AccountEntity>>();
Now we are working to spin off for main codebase to custom version of project and we need custom fields in data and occassional custom behavior in repository. Most of classes are fine with base implementation but others would require specific implementation. So my goal is to get to following services in:
var repository = new RealRepository<CustomAccountEntity>();
services.AddSingleton(IRepository<AccountEntity>, repository);
// for new classes
services.AddSingleton(IRepository<CustomAccountEntity>, repository);
I tried to add out T to IRepository but I am using T in input parameters and this gave compile time "Invalid variance" error.
I can see a solution by adding second type parameter to interface so it looks like:
IRepository<TBase, out TChild> : IQueriable<TChild> {
Save (T document);
}
Finally, Question: How can make change 100% backward compatible?
What I tried:
Add IRepository<T>: IRepository<T,T> -> complies, but RealRepository is not implementing IRepository anymore.
Add 2 interfaces in implementation: public class RealRepository<TBase, TChild>: IRepository<TBase, TChild>, IRepository<TChild> but this gives compliation error 'cannot implement both ... and ... because they may unify for some type parameter substitutions'
Save(T document) has T in a contravariant position. That means in T, not out T.
Let's recap what contravariance means. Suppose you had this code:
using System;
public class Entity {}
public class AccountEntity : Entity {}
public class CustomAccountEntity : AccountEntity {}
public interface IQueryable<in T>
where T : Entity
{}
public interface IRepository<in T>
where T : Entity
{
void Save(T record);
}
public class EntityRepository<T> : IRepository<T>
where T : Entity
{
public void Save(T record) {}
}
public class Program
{
public static void Main()
{
// This is ***VALID***:
IRepository<CustomAccountEntity> repo = new EntityRepository<AccountEntity>();
Console.WriteLine(repo == null ? "cast is invalid" : "cast is valid");
}
}
https://dotnetfiddle.net/cnEdcm
So whenever you need a IRepository<CustomAccountEntity>, you can use a concrete EntityRepository<AccountEntity> instance. Seems counter-intuitive, but it's actually totally right: If the concrete method is Save(AccountEntity), it can obviously handle CustomAccountEntity instances too; OTOH if the concrete method were Save(CustomAccountEntity), it would NOT be able to handle simple AccountEntity instances.
Having said that, then I think you should
Use contravariance instead;
Declare all dependencies using the most specialised type, e.g. IRepository<CustomWhateverEntity>;
In the IoC registration code, for each particular entity, setup either Repository<CustomeWhateverEntity>, if you need the extra behaviour, or just Repository<WhateverEntity> otherwise.
I'm trying to implement the Dependency Injection from Core on my software in order to replace Ninject and update everything to our new technology.
Btw, I'm facing a problem on some interfaces that are generic. For such cases I'm getting directly an Exception that the injector could not create an instance of my class.
I inserted above a small snippet of a sample case that puts me on fire.
services.AddTransient(typeof(IRepository), typeof(MyRepository<,>))
Is that way correct? How can I do that?
Class implementation:
public class MyRepository<TEntity, TContext> : IRepositoryBase
where TEntity : class
where TContext : IDbContext, new()
{
...
}
Interface:
public interface IRepository : IDisposable
{
...
}
Thanks!
This doesn't really make sense. You will be asking the container for IRepository, so how would it know what the generic type arguments should be such that it can give you a MyRepository<,>?
So when asked to return an object like this:
public class MyService
{
private IRepository<Something, SomethingElse> _repo;
public MyService(IRepository<Something, SomethingElse> repo)
{
// Container will actually give us MyRepository<Something, SomethingElse>
_repo = repo;
}
}
I would expect either:
services.AddTransient(typeof(IRepository<,>), typeof(MyRepository<,>));
or, if your repository doesn't need to be generic (I don't understand why it'd need two generic arguments as it is), then I'd expect this:
services.AddTransient(typeof(IRepository), typeof(MyRepository));
However, since there's no generics involved here, you could use the alternative form to achieve the same thing with less typing:
services.AddTransient<IRepository, MyRepository>();
So really the answer is to solve your interface/class design. Showing more of the implementation of them would help.
UPDATE
Your implementation needs to be:
Class implementation:
public class MyRepository<TEntity, TContext> : IRepository<TEntity, TContext>
where TEntity : class
where TContext : IDbContext, new()
{
...
}
Interface:
public interface IRepository<TEntity, TContext> : IDisposable
where TEntity : class
where TContext : IDbContext, new()
{
...
}
I ended up using Autofac and without any changes on my structure everything started working again.
Will wait a little more for documentation and more people using, so I can change my implementation to use MS DI.
To register all repositories use this:
var allRepositories = GetType().GetTypeInfo()
.Assembly.GetTypes().Where(p =>
p.GetTypeInfo().IsClass &&
!p.GetTypeInfo().IsAbstract &&
typeof(IRepository).IsAssignableFrom(p));
foreach (var repo in allRepositories)
{
var allInterfaces = repo .GetInterfaces();
var mainInterfaces = allInterfaces.Except
(allInterfaces.SelectMany(t => t.GetInterfaces()));
foreach (var itype in mainInterfaces)
{
services.AddScoped(itype, repo);
}
}
Then resolve it:
public YourClass(IRepository<T> repo)
{
//...
}
These days I'm facing this situation often and I'm looking for an elegant solution. I have :
public abstract class TypeA
{
public abstract void AbtractMethod(IDependency dependency);
}
public class TypeB : TypeA
{
public override void AbtractMethod(ISpecializedDependencyForB dependency) { }
}
public class TypeC : TypeA
{
public override void AbtractMethod(ISpecializedDependencyForC dependency) { }
}
public interface IDependency { }
public interface ISpecializedDependencyForB : IDependency { }
public interface ISpecializedDependencyForC : IDependency { }
My objective is to make things transparent in the client perspective and to consume this code like that :
TypeA myDomainObject = database.TypeARepository.GetById(id); // The important point here is that I don't know if the object is of TypeB or TypeC when I consume it.
IDependency dependency = ? // How do I get the right dependency
myDomainObject.AbtractMethod(dependency);
So the thing is that since I don't know the concrete type of the object, I can't inject the right dependency into it.
What I'm currently doing is that I create an abstract factory, to inject the right properties. I have two problems with that, the first one is that I would end up with a lot of factories. The second one is that it makes polymorphism useless since the client actually needs to care about "managing" the underlying type (I need to inject all the possible dependencies in the factory, and to instantiate the factory on the client code).
1) Therefore I was thinking of using property injection with unity, but I can't find out if it's possible to resolve the dependencies of an object, after it's been instanciated manually. Even with this approach I think I could still meet the same problem : I'm not sure if unity would check the actual type of the object and resolve the right dependency if a syntax like this existed :
unityContainer.Resolve<TypeA>(myDomainObject)
If not, I would need to know the type in advance and would be back to the same problem.
2) I have found this article mentionning that EF provides some mechanism for DI, but it seems that it is only meant to inject the framework services (PluralizationService, etc...). Otherwise it would have been a nice way to achieve that.
3) I could also not use DI in this case... It looks like by concept DI does not fit well with polymorphism. I'm not excited by this idea though.
I'd be happy to have a solution for the property injection I'm trying to achieve, or an idea of pattern I could use. However I really don't want to create a big infrastructure and obfuscate my code just for this purpose.
Note : I don't want to you use domain events in this case.
Thank you
TL;DR
Replace the IDependency parameter of the polymorphic AbstractMethod with an implementation-specific construction dependency parameter, which is injected by the IoC container, not by the consumer.
In more detail
The original class hierarchy will need to look like more like this for inheritance polymorphicism to work, as the superclass virtual method and subclass override methods must match signatures:
public abstract class TypeA // superclass
{
public abstract void AbtractMethod(IDependency dependency);
}
public class TypeB : TypeA // subclass 1
{
public override void AbtractMethod(IDependency dependency)
{
Contract.Requires(dependency is ISpecializedDependencyForB);
// ...
}
}
public class TypeC : TypeA // subclass 2
{
public override void AbtractMethod(IDependency dependency)
{
Contract.Requires(dependency is ISpecializedDependencyForC)
// ...
}
}
However, some things don't ring true with this design:
The LSP appears to be violated, since the although AbtractMethod() advertises that it accepts the base IDependency interface, the two subclasses actually depend on a specialized subclassed dependency.
It is also unusual, and arguably inconvenient, for a caller of these methods to build up the correct dependency and pass it to the method in order for it to be invoked correctly.
So, if possible, I would adopt a more conventional approach to the arrangement of dependencies, whereby the dependency is passed to the subclass constructor, and will be available to the polymorphic method when needed. This decouples the need to supply the appropriate IDependency to the method. Leave it to the IoC container to do the appropriate dependency resolution:
Use constructor injection to create the correct dependency into Classes TypeB and TypeC
If there is a secondary requirement to Expose an IDependency on the base class TypeA to consumers, then add an additional abstract property to TypeA of type IDependency (but this seems iffy)
As per Ewan's observation, the repository would need some kind of strategy pattern in order to serve up polymorphic domain entities (B or C). In which case, couple the repository to a factory to do exactly this. The concrete factory would need to be bound to the container in order to tap into Resolve().
So putting this all together, you might wind up with something like this:
using System;
using System.Diagnostics;
using Microsoft.Practices.Unity;
namespace SO29233419
{
public interface IDependency { }
public interface ISpecializedDependencyForB : IDependency { }
public interface ISpecializedDependencyForC : IDependency { }
public class ConcreteDependencyForB : ISpecializedDependencyForB {};
public class ConcreteDependencyForC : ISpecializedDependencyForC { };
public abstract class TypeA
{
// Your polymorphic method
public abstract void AbtractMethod();
// Only exposing this for the purpose of demonstration
public abstract IDependency Dependency { get; }
}
public class TypeB : TypeA
{
private readonly ISpecializedDependencyForB _dependency;
public TypeB(ISpecializedDependencyForB dependency)
{
_dependency = dependency;
}
public override void AbtractMethod()
{
// Do stuff with ISpecializedDependencyForB without leaking the dependency to the caller
}
// You hopefully won't need this prop
public override IDependency Dependency
{
get { return _dependency; }
}
}
public class TypeC : TypeA
{
private readonly ISpecializedDependencyForC _dependency;
public TypeC(ISpecializedDependencyForC dependency)
{
_dependency = dependency;
}
public override void AbtractMethod()
{
// Do stuff with ISpecializedDependencyForC without leaking the dependency to the caller
}
public override IDependency Dependency
{
get { return _dependency; }
}
}
public interface ITypeAFactory
{
TypeA CreateInstance(Type typeOfA);
}
public class ConcreteTypeAFactory : ITypeAFactory
{
private readonly IUnityContainer _container;
public ConcreteTypeAFactory(IUnityContainer container)
{
_container = container;
}
public TypeA CreateInstance(Type typeOfA)
{
return _container.Resolve(typeOfA) as TypeA;
}
}
public class TypeARepository
{
private readonly ITypeAFactory _factory;
public TypeARepository(ITypeAFactory factory)
{
_factory = factory;
}
public TypeA GetById(int id)
{
// As per Ewan, some kind of Strategy Pattern.
// e.g. fetching a record from a database and use a discriminating column etc.
return (id%2 == 0)
? _factory.CreateInstance(typeof (TypeB))
: _factory.CreateInstance(typeof (TypeC));
// Set the properties of the TypeA from the database after creation?
}
}
class Program
{
static void Main(string[] args)
{
// Unity Bootstrapping
var myContainer = new UnityContainer();
myContainer.RegisterType<ISpecializedDependencyForB, ConcreteDependencyForB>();
myContainer.RegisterType<ISpecializedDependencyForC, ConcreteDependencyForC>();
myContainer.RegisterType(typeof(TypeB));
myContainer.RegisterType(typeof(TypeC));
var factory = new ConcreteTypeAFactory(myContainer);
myContainer.RegisterInstance(factory);
myContainer.RegisterType<TypeARepository>(new InjectionFactory(c => new TypeARepository(factory)));
// And finally, your client code.
// Obviously your actual client would use Dependency Injection, not Service Location
var repository = myContainer.Resolve<TypeARepository>();
var evenNumberIsB = repository.GetById(100);
Debug.Assert(evenNumberIsB is TypeB);
Debug.Assert(evenNumberIsB.Dependency is ISpecializedDependencyForB);
var oddNumberIsC = repository.GetById(101);
Debug.Assert(oddNumberIsC is TypeC);
Debug.Assert(oddNumberIsC.Dependency is ISpecializedDependencyForC);
}
}
}
Could whatever it is that knows about the dependencies live behind an interface IDependencyProvider which has a function
IDependency GetDependency(Type type).
This could even just return an object and the class that realises the interface needs to know all the sub types and their associated dependencies.
AbstractMethod is then changed to:
void AbstractMethod(IDependencyProvider provider);
In your sub classes you then override this and call
var dependency = provider.GetDependency(this.GetType());
Your middle tier then knows nothing about the sub types or the sub dependencies.
It's an interesting problem, what I was thinking is that your repository knows about and creates the TypeB and TypeC classes and so you can add the correct dependency at that point
public class TypeARepository
{
private ISpecializedDependencyForB depB;
private ISpecializedDependencyForC depC;
public TypeARepository(ISpecializedDependencyForB depB, ISpecializedDependencyForC depC)
{
this.depB = depB;
this.depC = depC;
}
public TypeA GetById(string id)
{
if (id == "B")
{
return new TypeB(depB);
}
else
{
return new TypeC(depC);
}
}
}
The TypeB and TypeC would then implement their abstract methods with their private ref to the dependency rather than having it passed in in the method.
I come across this problem in various forms myself from time to time and it always seems to me that if there is that hard link between the types just having it setup via an injection config or the like is wrong. As it allows the installer to potentially set a bad config
This approach also allows you to inject your dependencies with unity
Thank you a lot for your interest in my question, I came up with a solution yesterday evening. The objective is to keep things transparent for the client and to take full advantage of polymorphism by syntaxes such as baseObjectReference.AbstractMethodCall().
I finally realized that I was able to achieve what I'm after by taking advantage of the static modifier and using it for DI purposes. So I have that :
public abstract class TypeA
{
public abstract void AbtractMethod();
}
public class TypeB : TypeA
{
private ISpecializedDependencyForB SpecializedDependencyForB
{
get
{
return GetSpecializedDependencyForB.CreateSpecializedDependencyForB();
}
}
public override void AbtractMethod() { // do stuff with dependency }
}
public static class GetSpecializedDependencyForB
{
public static ISpecializedDependencyForB DependencyForB
{
return CreateSpecializedDependencyForB();
}
public delegate ISpecializedDependencyForB CreateSpecializedDependencyForBDelegate();
public static CreateSpecializedDependencyForBDelegate CreateSpecializedDependencyForB;
}
And then, in my unity container I add this code :
public static void RegisterTypes(IUnityContainer container)
{
// .... registrations are here as usual
GetSpecializedDependencyForB.CreateSpecializedDependencyForB = CreateMyDomainService;
}
Having this method in the same unity config class :
private ISpecializedDependencyForB CreateMyDomainService()
{
return container.Value.Resolve<ISpecializedDependencyForB>();
}
And finally, I can simply use my object like this :
TypeA myDomainObject = database.TypeARepository.GetById(id);
myDomainObject.AbtractMethod();
And that's it !
So four things here :
The first one is that I inject the delegate that will create and instance of the service.
Then it is thread safe because static member is only written one time at the beginning of the application. All other accesses will be read. Moreover two threads won't share the same instance of the dependency since the delegate creates a new one all the time.
Also one interesting thing is that I can rely on my existing unity container configuration, no extra code is needed. It is important because my dependency may need other dependency to be constructed.
And finally the unity container is anyway also static, so there is no memory leak.
It's basically a manual and easy to set up "DI framework" sitting beside Unity.
And more importantly it works like a charm ! I'm finally satisfied with my design. I will only use this approach for polymorphic situations since injecting the right dependency in the method is easy for other situations. However it might be interesting to fully encapsulate the domain model using this approach.
This is probably asked before but I can't work it out. Maybe if I could get the title right I could goolge it.
I have got this generic repository interface:
public interface IRepository<TEntity>
{
TEntity Resolve<TEntity>(); // dummy function, just to get the idea
}
I also have a generic unit of work, which is able to resolve a generic repository:
public interface IUnitOfWork
{
IRepository<TEntity> GetGenericRepository<TEntity>() where TEntity : class;
}
So far so good.
But as real life continues, I would like to create a custom repository, with some specific funtions. So I was thinking: inheritance; like this:
public class SpecialRepository : IRepository<SomeEntityType>
{
public void SomeSpecialFunction() { };
}
Obviously, this type cannot be resolved with the GetGenericRepository methode so I thought: lets add a extra method to the IUnitOfWork interface:
public interface IUnitOfWork
{
//same old get generic repository
IRepository<TEntity> GetGenericRepository<TEntity>() where TEntity : class;
//the newly added.
T GetInheretedRepository<T>() where T : class;
}
I want to be able to call the unit of work with the special repository, something like this:
public test()
{
IUnitOfWork uow = new UnitOfWork();
//I want to make this call with a constraint on TemplateRepo
//to enforce it's type: IRepository<T> (which TemplateRepo is)
var y = uow.GetInheretedRepository<TemplateRepo>();
}
The question is: how can I restrict type T in T GetInheretedRepository<T>() where T : class; to be of type: IRepository<TEntity>?
I tried this:
public interface IUnitOfWork
{
//the newly added.
//error: Only class or interface could be specified as constraint
T GetInheretedRepository<T>() where T : class, IRepository; }
and
public interface IUnitOfWork
{
//the newly added.
//error: type argument missing
T GetInheretedRepository<T>() where T : class, IRepository<>;
}
that doesnt work.
I could drop the constrain as a quick-fix or perhaps create an inherited unit of work, but then; the question still remains.
The way to do this is by adding a second generic type argument, as follows:
TRepository GetInheretedRepository<TRepository, TEntity>()
where TRepository : IRepository<TEntity>
where TEntity : class;
Here you supply both the Repository type and the entity type. This way the C# compiler can check whether or not the type matches. Here's how to call it:
var rep = uow.GetInheretedRepository<SpecialRepository, SomeEntityType>();
rep.SomeSpecialFunction();
This obviously sucks, since you will have to specify both types. But more importantly, this sucks because you have to specify the concrete type, making your code take a dependency on a concrete type; a violation of the Dependency Inversion Principle.
I really would like to advice to to step away from a design where you depend on a concrete type, or even better, step away from a design where you have many methods on a specific repository class, because this violates both SRP, OCP and ISP and this will likely cause maintenance problems later on.
So instead, take a look at the application design that is described in this article.
You need to specify second Type like
public interface IUnitOfWork
{
//the newly added.
T GetInheretedRepository<T, TEntity>() where T : class, IRepository<TEntity>;
}
public interface IRepository<TEntity>
{
TEntity Resolve(); // dummy function, just to get the idea
}
example that compiles fine - https://dotnetfiddle.net/MmmPil
I am following a tutorial to do with the Repository Pattern in a combination with the Unit Of Work pattern.
I essentially have:
interface IRepository<T> where T : class
{
//...
}
class Repository<T> where T : class
{
//Implemented methods
}
interface IFooRepository
{
IQueryable<Foo> GetFoos();
}
class FooRepository : Repository<Foo>, IFooRepository
{
IQueryable<Foo> GetFoos() {}
}
The above represents my repositories, in a basic sense. I then have a Uow class.
public class MyUow
{
public void Commit() { }
public IRepository<Bar> Bars { get { return GetStandardRepo<Bar>(); } }
public IFooRepository Foos { get { return GetRepo<IFooRepository>(); } }
private IRepository<T> GetStandardRepo()
{
return RepositoryProvider.GetRepoistoryForEntityType<T>();
}
private T GetRepo<T>()
{
return RepositoryProvider.GetRepository<T>();
}
}
My problem is coming where the tutorial I am following only ever instansiates a Dictionairy<Type, object> in the RepositoryProvider class and doesn't seem to fill it, so the method used in GetRepo<T> doesn't work.
public virtual T GetRepository<T>(Func<DbContext, object> factory = null) where T : class
{
//Look for T in the dictionairy by typeof(T)
object repoObj;
Repositories.TryGetValue(typeof(T), out repoObj);
if (repoObj != null)
return (T)repoObj;
//Not found or a null value, make a new instance of the repository.
return MakeRepository<T>(factory, Context);
}
private T MakeRepository<T>(Func<DbContext, object> factory, DbContext dbContext) where T : class
{
var f = factory ?? _repositoryFactories.GetRepositoryFactory<T>();
if (f == null)
//Exception here because this is null
throw new NotImplementedException("No factory for repository type");
var repo = (T)f(dbContext);
Repositories[typeof(T)] = repo;
return repo;
}
My question is essentially what is the correct way to implement this pattern and where I am going wrong? Should I instansiate the Dictionairy<Type, Func<DbContext, object> with a the list of known repositories? This seems dirty. I am driving myself insane trying to solve this!
Thanks in advance.
What I see from beginning is that your Repository<T> doesn't implement IRepository<T>, so it should be like this:
class Repository<T> : IRepository<T> where T : class
{
//Implemented methods
}
Then your completely secret tutorial should describe how _repositoryFactories.GetRepositoryFactory<T>() can discover your IRepository<T> implementor FooRepository - maybe it willbe autodiscovery, maybe you need to register something somewhere.
Next, again I know nothing about your specific tutorial and factories etc, but I suppose you may need to use GetRepo<Foo> instead of GetRepo<IFooRepository>, because right now this IFooRepository looks meaningless... or maybe again you miss something in this IFooRepository declaration, and it should be like interface IFooRepository : IRepository<Foo> - and again, it greatly depends on particular discovery implementation for factories you are using.
In case you have not found the answer yet, I followed through the tutorial and was able to run it (the tutorial sample). If you're sure that you have implemented it right, take note of this,
The Repository Dictionary is by default, null and will only have value of the not standard repos (e.g. IFooRepository) when it is first requested. Therefore, if you're checking the value in debug of the Repository Dictionary and an IFooRepository is not yet requested it is for sure that you will not see it there. Have a code to access the IFooRepository first then it will make a repository for that in the MakeRepository method of the provider class.
Hope that helps
There is a helper class called RepositoryFactories.cs
You need to add an entry for your custom Repository to the dictionary
{typeof(IFooRepository ), dbContext => new FooRepository (dbContext)}