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)
{
//...
}
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.
My repository pattern is setup like this:
public interface IRepository<T> where T : class {}
public abstract class Repository<C, T> : IRepository<T>
where C : DbContext, IBaseContext
where T : class, IEntity
{}
public interface ICustomerRepository : IRepository<Customer>
{//specific methods here}
public class CustomerRepository : Repository<MyContext, Customer>, ICustomerRepository
I added the following method in my UoW class (and interface):
public TRepository GetRepository<TEntity, TRepository>()
where TEntity : class, IEntity
where TRepository : IRepository<TEntity>
{
object[] args = new object[] { (IDatabaseFactory<MyContext>)databaseFactory };
return (TRepository)Activator.CreateInstance(typeof(TRepository), args);
}
And in my service I try to get the repository doing the following:
var customerRepository = uow.GetRepository<Customer, CustomerRepository>();
In Autofac i'm using InstancePerRequest. So the UoW and the repository instances are created per request and disposed afterwards. Do I still need to implement caching of the repositories?
Is this the correct way to use repository factory?
NOTE
My UoW and repositories are located in a 'DAL' assembly, my services are in a different 'Service' assembly.
A factory's only job is to construct instances of classes. So in that sense, your factory is correct.
Your IoC container is already managing the life time of the object so there is no need to duplicate that work.
My question is this: Why even have a factory? Your IoC container is already capable of constructing instances. Why not just request an ICustomerRepository from Autofac directly and have it construct for you, instead of requesting a custom object who's only job is to do what Autofac can do out of the box?
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)}
I am currently developing an MVC 3 application with EF and the Repository pattern. I created a generic interface as follows:
interface IGenericRepository<T>
{
}
And an abstract class as follows:
abstract class GenericRepository<TContext ,T> : IGenericRepository<T>
where TContext : DbContext, new()
{
}
After that my repo inherits both of them like this:
interface ICardRepository : IGenericRepository<Card>
{
}
and
class CardRepository : GenericRepository<EfContext, Card>,
ICardRepository
{
}
With Unity I register the interface and the class like this:
container.RegisterType<ICardRepository, CardRepository>();
Now the question is: can I use IGenericRepository instead of ICardRepository?
Like this:
container.RegisterType<IGenericRepository<Card>, CardRepository>();
In theory I can, but as I still do not get how this pattern works I am not quite sure if I am not breaking or missing something.
One possible issue is now you will have to resolve IGenericRepository<Card>, instead of ICardRepository.
This will not work:
var cardRepository = container.Resolve<ICardRepository>();
Instead you will have to do this:
var cardRepository = container.Resolve<IGenericRepository<Card>>();
This also means that if you are doing something like constructor injection, you can't use:
public class SomethingDependentOnCardRepository
{
// The parameter type should be IGenericRepository<Card> instead,
// if you are using Unity to resolve this dependency.
public SomethingDependentOnCardRepository(ICardRepository cardRepository)
{
// code
}
}
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);