Using WithConstructorArgument and creating bound type

笑着哭i 提交于 2019-12-13 06:21:35

问题


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>());

回答1:


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;
}


来源:https://stackoverflow.com/questions/8580071/using-withconstructorargument-and-creating-bound-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!