I have a binding that looks like this:
kernel.Bind<IRepository<Holiday>>().To<RepositoryBase<Holiday>>();
The problem is that RepositoryBase takes a contructor paramter of UnitOfWork called context. This is not, in and of itself a problem. Ninject should resolve it. Except for the fact that I have two UnitOfWork implementations, both bound using an attribute discriminator.
kernel.Bind<IUnitOfWork>().To<MS_DevEntities>().WhenTargetHas<MsDataAttribute>()
.InRequestScope();
How can specify that when an IRepository is created, it should be created with MS_DevEntities?
Certainly, i could do something like this:
kernel.Bind<IRepository<Holiday>>().To<RepositoryBase<Holiday>>()
.WithConstructorArgument("context", new MS_DevEntities());
However, I would prefer to have Ninject create the instance, particularly because i'm using the .InRequestScope() lifecycle.
Any suggestions?
EDIT:
Previously, I was using a class that looked like this:
public class HolidayRepository : RepositoryBase<Holiday>, IHolidayRepository
{
public HolidayRepository([MsData]IUnitOfWork context) : base(context){}
}
However, I now find myself with several dozen of these and they don't do much but add extra work when I need to create a new repository. I'd like to just map these directly in the bindings.
EDIT2:
I suppose I could do something like this, but it seems kind of hackish. Is there a better way?
kernel.Bind<MS_DevEntities>().ToSelf().InRequestScope();
kernel.Bind<IRepository<Holiday>>().To<RepositoryBase<Holiday>>()
.WithConstructorArgument("context",
(context) => context.Kernel.Get<MS_DevEntities>());
E.g. Put the attribute to the entity and use something like this:
kernel.Bind(typeof(IRepository<>)).To(typeof(RepositoryBase<>));
kernel.Bind<IUnitOfWork>().To<MS_DevEntities>()
.When(r => EntityHas<MsData>(r));
kernel.Bind<IUnitOfWork>().To<TheOtherOne_DevEntities>()
.When(r => EntityHas<TheOtherData>(r));
bool EntityHas<TAttribute>(IRequest r)
{
return r.Target.Member.ReflectedType.IsGenericType &&
r.Target.Member.ReflectedType.GetGenericArguments()[0]
.GetCustomAttributes(typeof(TAttribute), false).Any();
}
You can do everything using this When
condition and take the entity type from r.Target.Member.ReflectedType.GetGenericArguments()[0]
to lookup somewhere which UoW that you have to use for this entity type.
2nd approch using config
kernel.Bind<IUnitOfWork>().To<TheOtherOne_DevEntities>()
.When(r => EntityNeedsUoW(r, 1));
bool EntityNeedsUoW(IRequest r, int id)
{
return UoWConfig.GetDbIdForEntity(
r.Target.Member.ReflectedType.GetGenericArguments()[0]) == id;
}