В 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 всегда по имени. На самом деле, есть способ получить экземпляр из привязки без имени. Но поскольку я от всей души рекомендую не делать этого, я не показываю, как это сделать здесь. Если вы все еще хотите сделать это таким образом, я расскажу вам позже, как это будет работать.

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

  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>();
    
Другие вопросы по тегам