Использование WithConstructorArgument и создание связанного типа - PullRequest
0 голосов
/ 20 декабря 2011

У меня есть привязка, которая выглядит следующим образом:

kernel.Bind<IRepository<Holiday>>().To<RepositoryBase<Holiday>>();

Проблема в том, что RepositoryBase принимает параметр-конструктор UnitOfWork, называемый context.Это само по себе не является проблемой.Ninject должен решить это.За исключением того факта, что у меня есть две реализации UnitOfWork, каждая из которых связана с использованием дискриминатора атрибута.

kernel.Bind<IUnitOfWork>().To<MS_DevEntities>().WhenTargetHas<MsDataAttribute>()
    .InRequestScope();

Как можно указать, что при создании IRepository его следует создавать с помощью MS_DevEntities?

Конечно, я мог бы сделать что-то вроде этого:

kernel.Bind<IRepository<Holiday>>().To<RepositoryBase<Holiday>>()
    .WithConstructorArgument("context", new MS_DevEntities());

Однако я бы предпочел, чтобы Ninject создал экземпляр, особенно потому, что я использую жизненный цикл .InRequestScope ().

Есть какие-нибудь предложения?

РЕДАКТИРОВАТЬ:

Раньше я использовал класс, который выглядел так:

public class HolidayRepository : RepositoryBase<Holiday>, IHolidayRepository
{
    public HolidayRepository([MsData]IUnitOfWork context) : base(context){}
}

Однако теперь я нахожу себяс несколькими десятками из них, и они мало что делают, но добавляют дополнительную работу, когда мне нужно создать новый репозиторий.Я хотел бы просто отобразить их непосредственно в привязках.

EDIT2:

Полагаю, я мог бы сделать что-то подобное, но это выглядит как хакерский.Есть ли лучший способ?

kernel.Bind<MS_DevEntities>().ToSelf().InRequestScope();
kernel.Bind<IRepository<Holiday>>().To<RepositoryBase<Holiday>>()
    .WithConstructorArgument("context", 
        (context) => context.Kernel.Get<MS_DevEntities>());

1 Ответ

5 голосов
/ 21 декабря 2011

Например, поместите атрибут в сущность и используйте что-то вроде этого:

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

Вы можете сделать все, используя это условие When, и взять тип сущности из r.Target.Member.ReflectedType.GetGenericArguments()[0], чтобы найти где-нибудь, что UoW, чтоВы должны использовать для этого типа объекта.

2-й подход с использованием конфигурации

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