В Ninject 2.0, как у меня есть общая привязка и привязка для конкретного случая?
У меня есть ситуация, когда я хочу, чтобы зависимости вводили мой пользовательский объект, но также помещали текущего пользователя в контейнер 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: Ошибка при активации пользователя Доступно несколько подходящих привязок. Путь активации: 1) Запрос на пользователя Предложения: 1) Убедитесь, что вы определили привязку для пользователя только один раз.
Я понимаю ошибку, поскольку именованная привязка не ограничивает применение этой привязки, поэтому применяются обе привязки. Кажется очевидным, что мне нужно использовать контекстную привязку с методами.When*(), но я не могу придумать никакого способа сделать это. Я чувствую, что должно быть, когда методы, которые определяют, применяется ли именованный экземпляр. Что-то вроде:
// Not valid Ninject syntax
Bind<User>().ToSelf().WhenUnnamedRequested();
Bind<User>().ToMethod(LoadCurrentUser).WhenNamedRequested().InRequestScope().Named("Current");
Я не могу найти место на IRequest
интерфейс или его свойства, которые говорят мне имя запрошенное. Как мне это сделать?
1 ответ
На этот вопрос ответили в списке рассылки: http://groups.google.com/group/ninject/browse_thread/thread/cd95847dc4dcfc9d?hl=en
Если вы обращаетесь к пользователю, вызывая Get в ядре (что, я надеюсь, у вас нет), тогда дайте первой привязке также имя и получите доступ к User всегда по имени. На самом деле, есть способ получить экземпляр из привязки без имени. Но поскольку я от всей души рекомендую не делать этого, я не показываю, как это сделать здесь. Если вы все еще хотите сделать это таким образом, я расскажу вам позже, как это будет работать.
Если вы делаете это лучшим и предпочтительным способом и внедряете пользователя в объекты, которые требуют его как зависимости, есть два варианта:
- Более простой способ: дать первой привязке имя и добавить именованный атрибут к параметрам, например, ctor([Named("NewUser") IUser newUser, [Named("Current")] IUser currentUser)
Или предпочтительный способ сохранить классы реализации свободными от инфраструктуры IoC: укажите пользовательские атрибуты и добавьте их в параметры, например, ctor([NewUser] IUser newUser, [CurrentUser]IUser currentUser). Измените привязки на:
Bind<User>().ToSelf() .WhenTargetHas<NewUserAttribute>(); Bind<User>().ToMethod(LoadCurrentUser) .InRequestScope() .WhenTargetHas<CurrentUserAttribute>();