I have a base class that has a repository injected into the constructor, now any class that I derive off of it now also needs those parameters, but the repository is only used by the base class, is there a way to bind Ninject to just the base class and not go through the constructor? And most importantly, is it a good idea?
public class HtmlPageModel
{
private readonly IHtmlPageRepository _repository;
public HtmlPageModel (IHtmlPageRepository repository)
{
_repository = repository;
}
}
public class VideoPageViewModel : HtmlPageModel
{
public VideoPageViewModel(IHtmlPageRepository repository) : base(repository)
{
}
}
View models shouldn't have dependencies at all. Inject the repository into the controller and assign the values from there.
Also if many pages are using the same base view model this indicates that some part of the page is shown in many situations or even all the time. In this case it is better to have a custom controller and view for this area and use Html.RenderAction to render this part.
I still stand to my previous comment: You have to rethink your class hierarchy, this is not something you should work around with Ninject.
If your base class accepts a repository, so should all of your derived classes. As an alternative you could however inject a specially NullRepository into your VideoPageViewModel which basically does nothing (see Null Object pattern)
Binding by target type can be achieved using WhenInjectedInto() in Ninject:
kernel.Bind<IHtmlPageRepository>()
.To<HtmlPageRepository>()
.WhenInjectedInto<HtmlPageModel>();
kernel.Bind<IHtmlPageRepository>()
.To<NullRepository>()
.WhenInjectedInto<VideoPageViewModel>();
This is basically the same answer as brokenGlass. Why not just create another base class, and move the attributes/functionality from the your current base class into that one, but don't move the constructor/functionality that relates to the repository.
Related
In the code I am working on I have a structure where some portions of the code depend on the current software session. Software session contains multiple helper objects which are dependency injected by composition.
One example is IRepository injected to it, which contains access to the data repository. And the IRepository contains a DatabaseContext which writes to a database, via IDbContext again which is injected.
SoftwareSession is the only injected common infrastructure for accessing all the way to the database, acting as a gateway. This means when I want to write an object to database, for instance WriteCar I will have to implement 3 interfaces, 2 functions delegating to composed objects and 1 function with implementation. It is clarified in the code fragment below. The WriteCar signatures are defined the same in 3 interfaces (IRepository, ISoftwareSession, IDbContext), 2 places where it is not implemented (Repository, SoftwareSession) which simply calls composited objects related functions and 1 place of actual implementation (IDbContext)
This means when I want to refactor, move code, add functionality or change function signatures I will always have to change 6 places for one function.
I think this provides the best environment for improving testability and it follows best practices where software session wraps access to repository and repository wraps access to data contexts - yet I still am questioning if we can have some better way of writing it once, or do I have a misunderstanding of some concept in the code below?
What is the architecturally more maintainable way of implementing this? Maybe even using some clever way of lambdas or delegates to reduce the amount of code written for each new functionality? Or even some libraries (like automapper simplifies DTOs) or tools to ease generation of this code from some kind of templating mechanism using Visual Studio, Resharper, etc?
Please let me know if I am having some confusion of concepts here. I know some my colleagues have similar views, in which case it may be helpful to clarify misunderstandings of others as well.
public class SoftwareSession : ISoftwareSession
{
...
IRepository repository;
public void WriteCar(Car car){
repository.WriteCar(car);
}
...
}
public interface ISoftwareSession{
...
void WriteCar(Car car);
...
}
public class Repository : IRepository{
...
IDbContext context;
public void WriteCar(Car car){
context.WriteCar(car);
}
...
}
public interface IRepository{
...
void WriteCar(Car car);
...
}
public class MyDbContext : IDbContext{
...
public void WriteCar(Car car){
//The Actual Implementation here.
...
}
...
}
public interface IDbContext{
...
void WriteCar(Car car);
...
}
For one thing, your IDbContext and IRepository are the same. You would probably like to remove IDbContext, or at least to remove methods declared in IRepository from it.
Then, both MyDbContext and Repository would implement IRepository and Repository class would just be a wrapper around MyDbContext.
Then, if Repository is only forwarding calls to MyDbContext, then you probably don't need that class either.
Furthermore, I don't see that you are doing anything in the SoftwareSession apart from forwarding the call to the contained repository. Do you really need SoftwareSession, or would it make sense to pass IRepository directly to whoever is calling the session object?
Bottom line is that this implementation is swarming with duplication and forwarding. Remove that, and your entire model would become simple.
Without seeing your composition root, I'm not entirely sure how your implementation works, but I'd suggest looking into using an Inversion of Control (IoC) container. Since your ISoftwareSession implementation only depends on an IRepository instance, you only need to inject that in the class' constructor. The same goes for your IRepository implementation: you only need to inject your IDbContext into the constructor.
With the IoC container, you "register", i.e. wire up your interfaces to your implementation at application startup (in the composition root), and the container takes care of creating the required instances when you resolve the dependencies. Then all you have to do is get the instance of SoftwareSession from the container, and away you go.
So, you could change your SoftwareSession implementation like this:
public class SoftwareSession : ISoftwareSession
{
IRepository repository;
public SoftwareSession(IRepository repository)
{
this.repository = repository;
}
public void WriteCar(Car car)
{
repository.WriteCar(car);
}
}
And your Repository implementation like this:
public class Repository : IRepository
{
IDbContext context;
public Repository(IDbContext dbContext)
{
context = dbContext;
}
public void WriteCar(Car car)
{
context.WriteCar(car);
}
}
Then here is your composition root:
var ioc = new MyIocContainer();
// register your interfaces and their associated implementation types with the IoC container
ioc.Register<ISoftwareSession, SoftwareSession>();
ioc.Register<IRepository, Repository>();
ioc.Register<IDbContext, MyDbContext>();
// resolve the IoC container
ioc.Resolve();
// get your `ISoftwareSession` instance
var session = ioc.GetConcrete<ISoftwareSession>();
var newCar = new Car();
session.WriteCar(newCar);
I've been gifted having had to work with an already set up Ninject DI based application which I have grown and added to considerably over the development of an application I'm working on.
I now find a problem that I would like to correct. I've managed to work around it using inheritance but would like a more cleaner solution.
I have two connections required to be injected into different services and repositories. I then need the repositories to also be correctly linked to the correct service having the same UnitOfWork.
I think I might be asking something that is not possible without inheritance and specialisation but that is why I am asking.
I managed to resolve this by creating a sub class of the main Repository and UnitOfWork classes but does nothing apart from implementing the base class.
I just don't like the idea of a sub class that is fully dependant on the super class functionality with basically empty braces apart from constructor, to me this doesn't seem true OOP just to resolve this problem. So I sought for a better solution utilising a one class solution if possible in DI.
So if you can ignore the solution I have spoken about because I completely reverted the change this is what I am left with:
Looking at the code below you can see what is the objective.
...
public class UnitOfWork : IUnitOfWork
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger("UnitOfWork");
public DbContext DataContext { get; set; }
public UnitOfWork(string connectionString)
{
DataContext = new DbContext(connectionString);
}
public void Commit()
{
...
}
}
...
public class Repository<T> : IRepository<T> where T : class
{
public IUnitOfWork unitOfWork { get; set; }
private readonly IDbSet<T> dbSet;
//private static readonly log4net.ILog log = log4net.LogManager.GetLogger("Repository");
public Repository(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
dbSet = this.unitOfWork.DataContext.Set<T>();
}
...
}
...
public class IPOPDataModules : NinjectModule
{
public override void Load()
{
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BE_TESTEntities"].ConnectionString);
Bind<IRepository<tOrder>>().To<Repository<tOrder>>().InRequestScope();
}
}
...
public class DataModules : NinjectModule
{
public override void Load()
{
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BAPSEntities"].ConnectionString);
Bind<IRepository<Data.Quote>>().To<Repository<Data.Quote>>().InRequestScope();
}
}
...
public class QuoteService : IQuoteService
{
private IUnitOfWork unitOfWork;
private IRepository<Data.Quote> quoteRepository;
public QuoteService(IUnitOfWork unitOfWork, IRepository<Data.Quote> quoteRepository)
{
...
}
}
...
public class IPOPService : IIPOPService
{
private IUnitOfWork unitOfWork;
private IRepository<Data.tOrder> tOrderRepository;
public IPOPService(IUnitOfWork unitOfWork, IRepository<Data.tOrder>)
{
...
}
}
What I want to know is, is it possible to share the same UnitOfWork and Repository objects by two different connections and have them injected as different instances to the respective services (IPOPService for IPOP_BE_TEST connection, QuoteService for IPOP_BAP connection)
Again the code above doesn't achieve want I want but this is the sort of architecture I would like to play around to get this to work.
What you're looking for are Ninject binding scopes. Whenever you declare a binding Ninject will provide a delegate to that binding that the activation process uses to determine if it should create a new instance of that service, or if it should return a previously constructed instance.
So, if you want to implement a singleton in Ninject, you simply declare a binding that looks like this:
Bind<IRepository<Data.Quote>>().To<Repository<Data.Quote>>().InSingletonScope();
InSingletonScope() and InRequestScope() are simply sugar (or in the case of InRequestScope an extension method) on IBindingInSyntax<T> for the InScope(Func<Ninject.Activation.IContext, object> scope) method though. Any time you want to ensure that Ninject returns the same instance of a service in a given situation, all you need to do is implement a custom scope.
If I understand your question correctly, you want to ensure that when a request hits your application the same instances of Repository<T> and IUnitOfWork will be injected into all the services in your application. In this case you would simply have to write bindings like this:
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BE_TESTEntities"].ConnectionString);
Bind<IRepository<tOrder>>().To<Repository<tOrder>>().InRequestScope();
However, your problem appears to be that you have two separate modules, with two separate bindings. I would suggest that you need to use a single module with contextual binding to determine which connection string should be provided to which part of the system. So your one module might look like this:
Bind<IUnitOfWork>()
.To<UnitOfWork>()
.WhenInjectedInto<IIPOPService>()
.InRequestScope()
.WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BE_TESTEntities"].ConnectionString);
Bind<IUnitOfWork>()
.To<UnitOfWork>()
.WhenInjectedInto<IQuoteService>()
.InRequestScope()
.WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["IPOP_BAPSEntities"].ConnectionString);
Bind<IRepository<tOrder>>().To<Repository<tOrder>>().InRequestScope();
This way you can be sure that when Ninject is resolving IIPOPService it will create an instance of UnitOfWork initialized with the "IPOP_BE_TESTEntities" connection string, and when resolving IQuoteService, it will use the "IPOP_BAPSEntities" connection string, but otherwise, across that request scope, only a single instance will be constructed by Ninject.
Hope this helps.
Your question is not completely clear for me. But check the documentation for the following two scopes, which might be interesting for your scenario.
InCallScope will result that only one instance will be created per resolution tree. I usually use this scope on desktop applications for a unit of work. See the documentation here. You'll need the Ninject.Extensions.NamedScope extension for this.
InRequestScope will result that in a web application, only one instance will be created per HTTP request. I usually use this scope for a unit of work. See the documentation here. You'll need the Ninject.Web.Common package for this.
I'm developing a repo layer with several different repos like UserRepository, ReportRepository, etc. The connection string will be injected through the constructor of the repo. This pattern will be implemented consistently for all repos. Is there a way I can implement this logic generically without having to repeat this implementation for each repo? Each repo currently implements a corresponding interface. For example, UserRepository : IUserRepository. Is there a pattern you normally use to avoid the duplicate code? I could use abstract classes but I'm wondering if that would be too heavy. I've always seen repo classes implementing interfaces in past solutions I've worked on
Just use a base class, the typical pattern is:
public class UserRepository : IUserRepository,
RepositoryBase
{
public UserRepository(string connectionString)
: base(connectionString)
{
}
}
and put common code in RespositoryBase.
I've a base class for business logic operations that is being inherited by my co-worker. This class expose a constructor which requires an objectContext as parameter. You can think of this base class as a component for atomic CRUD operations (all its select, insert, edit and delete method will always act on just one entity).
Then, I have a "super class" which its primary purpose is shared the objectContext between all the above base class in order to execute some business transaction and also it must provide any baseClass instance, if required.
So, I'm looking for to elegant way to "inject" superClass's objectContext into a baseclass:
public BaseClass<T> where T : entity
{
private ObjectContext _ctx;
public BaseClass(ObjectContext ctx){ _ctx = ctx;}
public virtual IList<T> Select(){..}
public cirtual voind Insert(T entity){..}
// other stuff
}
public class SuperClass
{
private ObjectContext _ctx = new...
public BaseClass<TEntity> LoadBaseClass(TBase, TEntity) where TBase : BaseClass<TEntity>, where TEntity : class
{
BaseClass<TEntity> obj = Activator.CreateInstance(typeof(TBase), _ctx); // share objectContext
}
public int SaveAll(){return _ctx.SaveChanges();}
}
As you can see, my super class is able to return some baseClass instance through its type and it's just what I want. However, if some inherited class defines its own contructor with other parameter my LoadBaseClass method will fails.
I would find a clean solution in order to avoid any kind of possibility of error during instance creations from LoadBaseClass method. The only way I know is to define a private contructor, but by this way no-one will be able to inherit baseclass anymore..
What you are looking for is called Dependency Injection. You are now trying to build this by hand but there are a lot of tools that already do what you want.
Dependency Injection is all about constructing objects and configuring how and when those objects are created. It comes down to splitting object creation from your business logic.
In your case, you are working with something called the Unit Of Work and Repository pattern. Using a Dependency Injection container like Ninject you can easily configure your UnitOfWork to be shared between all repositories like this:
var kernel = new StandardKernel();
kernel.Bind<IMyRepository>().To<ConcreteRepository();
kernel.Bind<IMyUnitOfWork>().To<ObjectContextImp>().InRequestScope();
IMyRepository repos = kernel.Get<IMyRepository>();
What Ninject (or any DI tool) will do is try to construct a IMyRepository. You've configured it to look for a ConcreteRepository. Then it notices that the ConcreteRepository takes a IMyUnitOfWork in its constructor. In this case you have mapped this to your ObjectContextIml and added the InRequestScope option.
InRequestScope is for ASP.NET web applications and it means that your context should be created once for each request. Ninject has a couple of different Object Scopes that you can use to configure how your object should be created and shared.
This way, you have complete control over how your objects are created.
I'm out of ideas how to configure right Windsor container for use with repositories in Windows app.
I have generic repository implementation Repository, where T is entity type, it has a dependency IDatacontextProvider, which provides datacontext for it:
public class Repository<T> : IRepository<T> where T : class
{
protected DataContext DataContext;
public Repository(IDataContextProvider dataContextProvider) {
DataContext = dataContextProvider.DataContext;
}
....
}
And for simple things everything works ok with following configuration:
container.Register(
Component.For<IDataContextProvider>()
.ImplementedBy<DataContextProvider>()
.Lifestyle.Transient,
Component.For(typeof(IRepository<>))
.ImplementedBy(typeof(Repository<>))
.Lifestyle.Transient, ....
Problems occur, when i try to join different entities from several repositories, as long as each repository instance has different data context instance.
For example i have simple service:
public class SimpleService : ISimpleService {
public SimpleService(IRepository<Order>, IRepository<OrderLine>) {
....
}
}
I could make IDataContextProvider as Singleton, but i think that would bring even bigger problems.
I could pass IDataContextProvider to SimpleService, and try to resolve repository instances there, but that would require additional code to make service easy testable and would require additional dependencies.
May be somebody has a better idea how to solve this?
update:
following advice, I've created repository factory (it's little bit different from proposed in answer, it does not have direct dependency to datacontext, but idea is very same):
public interface IRepositoryFactory
{
IRepository<T> GetRepository<T>() where T:class;
}
public class RepositoryFactory : IRepositoryFactory
{
private readonly IDataContextProvider dataContextProvider;
public RepositoryFactory(IDataContextProvider dataContextProvider)
{
this.dataContextProvider = dataContextProvider;
}
public IRepository<T> GetRepository<T>() where T : class
{
return new Repository<T>(dataContextProvider);
}
}
What about having another layer in between, such as a RepositoryFactory? That one could have a transient lifestyle. All repositories created from the factory would share the same DataContext instance. You would also need to change your repository classes so they take a DataContext instance instead of a DataContextProvider.
public class RepositoryFactory : IRepositoryFactory
{
protected DataContext dataContext;
public RepositoryFactory(IDataContextProvider provider)
{
dataContext = dataContextProvider.DataContext;
}
public IRepository<T> GetRepository<T>()
{
return new Repository<T>(dataContext);
}
}
public class SimpleService : ISimpleService {
public SimpleService(IRepositoryFactory factory) {
....
}
}
IDatacontextProvider sounds like a factory interface and these are usually defined as singletons in the dependency injection. I see several potential paths to a solution:
I don't know about particulars of your application, but maybe you can write your own lifestyle manager for IDatacontextProvider (since you say neither singleton nor transient suits you).
If you want to ensure the same IDatacontextProvider is passed among repositories, maybe you should think about providing it explicitly as a method parameter, instead of an injected dependency.
#Can's answer is also a possible solution, I've used that one myself once.
Your problem is in the configuration of the lifestyle. I had the same issues. You have to configure your repositories with an PerWebRequest lifestyle. This gave me an nice performance boost and reducing my errors from dozens to zero.
On my blog you can find an simple example http://marcofranssen.nl of dependency injection in combination with mvc3 and EF Code first.