В Ninject 2.0, как у меня есть общая привязка и привязка для конкретного случая? - PullRequest
8 голосов
/ 09 сентября 2010

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

kernel.Get<User>(); // Should return a new User()
kernel.Get<User>("Current"); // Should return the current user

Можно подумать, что такие привязки будут работать:

Bind<User>().ToSelf();
Bind<User>().ToMethod(LoadCurrentUser).InRequestScope().Named("Current");

Конечно, это дает:

Ninject.ActivationException: Error activating User
More than one matching bindings are available.
Activation path:
1) Request for User

Suggestions:
1) Ensure that you have defined a binding for User only once.

Я понимаю ошибку, поскольку именованная привязка не ограничивает применение этой привязки, поэтому применяются обе привязки.Кажется очевидным, что мне нужно использовать контекстную привязку с методами .When * (), но я не могу придумать никакого способа сделать это.Я чувствую, что должно быть, когда методы, которые определяют, применяется ли именованный экземпляр.Что-то вроде:

// Not valid Ninject syntax
Bind<User>().ToSelf().WhenUnnamedRequested();
Bind<User>().ToMethod(LoadCurrentUser).WhenNamedRequested().InRequestScope().Named("Current");

Я не могу найти никакого места в интерфейсе IRequest или его свойствах, которые сообщают мне запрошенное имя.Как мне это сделать?

1 Ответ

3 голосов
/ 29 октября 2010

На этот вопрос ответили в списке рассылки: http://groups.google.com/group/ninject/browse_thread/thread/cd95847dc4dcfc9d?hl=en


Если вы обращаетесь к пользователю, вызывая Get в ядре (что, я надеюсь, нет), тогда присвойте первой привязке также имя и получите доступ к User всегда по имени. На самом деле, есть способ получить экземпляр из привязки без имени. Но поскольку я от всей души рекомендую не делать этого, я не показываю, как это сделать здесь. Если вы все еще хотите сделать это таким образом, я расскажу вам позже, как это будет работать.

Если вы делаете это лучшим и предпочтительным способом и вводите пользователя в объекты, которые требуют его в качестве зависимости, есть два варианта:

  1. Более простой : Дайте первой привязке имя и добавьте именованный атрибут к параметрам, например. ctor ([Named ("NewUser") IUser newUser, [Named ("Current")] IUser CurrentUser)
  2. Или предпочтительный способ для защиты классов реализации от структуры IoC: укажите пользовательские атрибуты и добавьте их в параметры, например, ctor ([NewUser] IUser newUser, [CurrentUser] IUser currentUser). Измените Привязки на:

    Bind<User>().ToSelf()
                .WhenTargetHas<NewUserAttribute>();
    Bind<User>().ToMethod(LoadCurrentUser)
                .InRequestScope()
                .WhenTargetHas<CurrentUserAttribute>();
    
...