2013-05-31 3 views
8

У меня есть статический класс, и мне нужно вставить в него несколько экземпляров. Статический класс может иметь статический конструктор, но он должен быть без параметров. Итак, как я могу что-то вбить?Ninject и статические классы - как?

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

public static class AuthenticationHelper 
{ 
    // Fields. 
    private static object _lock = new object(); 
    private static readonly UserBusiness _userBusiness; // <-- this field needs to be injected. 

    // Public properties. 
    public static User CurrentUser 
    { 
     get 
     { 
      if (IsAuthenticated) 
      { 
       User user = (User)Context.Session[SessionKeys.CURRENT_USER]; 

       if (user == null) 
       { 
        lock (_lock) 
        { 
         if (user == null) 
         { 
          user = _userBusiness.Find(CurrentUserId); 
          Context.Session[SessionKeys.CURRENT_USER] = user; 
         } 
        } 
       } 

       return user; 
      } 

      return null; 
     } 
    } 
    public static int CurrentUserId { get; /* implementation omitted for brevity */ } 
    public static bool IsAuthenticated { get; /* implementation omitted for brevity */ } 
} 

информация Справочная информация: это приложение MVC4, поэтому я использую ninject.mvc3 плагин.

PS: Я видел некоторые вопросы, касающиеся Ninject и статических методов, но ни один из них, похоже, не рассматривал такую ​​проблему.

Заранее спасибо.

ответ

16

Не делайте этого. Не используйте статический класс, для которого нужны собственные зависимости. Это делает тестирование сложнее и другие типы, которые зависят от этого AuthenticationHelper, не смогут включить его в свой конструктор, что означает, что они скрывают тот факт, что они зависят от него.

Вместо этого просто сделайте то, что вы всегда будете делать: сделайте AuthenticationHelper нестатический, реализуйте интерфейс IAuthenticationHelper и введете все зависимости через свой публичный конструктор.

Но если вы настаиваете на том, чтобы этот класс статично (что опять-таки действительно плохая идея), создайте на нем статический метод Initialize(UserBusiness userBusiness) и вызовите этот метод на пусковом пути вашего приложения. Вы не можете позволить вашему контейнеру DI использовать этот статический метод. Они не позволяют, потому что 1. это плохая идея, и 2. такой статический метод нужно вызывать только один раз, поэтому позволить вашему контейнеру автоматически подключать это для вас, на самом деле не помогает.

+0

я вижу. Я не понимал, что это была такая плохая практика, но с вашим объяснением я теперь могу это понять и буду следовать твоему совету. В любом случае, хорошо знать, как обойти это, если нет другого выбора. Благодаря! –

+1

Это правда, иногда вы не можете. Например, при внедрении Injection Dependency в устаревшие приложения вам придется двигаться небольшими шагами. На этих временных шагах может быть такое решение. Это уродливо, это техническая глубина, но временная (по крайней мере, это должно быть). Но если ваше приложение уже создано с использованием DI, на самом деле нет причин для этого. – Steven

1

В качестве примечания, блокировка абсолютно бесполезна, поскольку вы блокируете доступ к локальной переменной «пользователь», которая не будет меняться между строками 2 «if (user == null)».

Ваше намерение состоит в том, чтобы заблокировать доступ к [CURRENT_USER] элемент Context.Session, так ..

  User user = (User)Context.Session[SessionKeys.CURRENT_USER]; 

      if (user == null) 
      { 
       lock (_lock) 
       { 
        user = (User)Context.Session[SessionKeys.CURRENT_USER]; 
        if (user == null) 
        { 
         user = _userBusiness.Find(CurrentUserId); 
         Context.Session[SessionKeys.CURRENT_USER] = user; 
        } 
       } 
      }