Задача с круговой привязкой Singleton - PullRequest
0 голосов
/ 30 декабря 2010

Я пытаюсь создать класс Singleton, как показано ниже, где MyRepository лежит в отдельном проекте DAL.Это вызывает у меня проблему с циклической ссылкой, потому что метод GetMySingleTon() возвращает класс MySingleTon и нуждается в его доступе.Точно так же мне нужен MyRepository доступ в конструкторе MySingleTon класса.

  public class MySingleTon
  {
    static MySingleTon()
    {
      if (Instance == null)
      {
        MyRepository rep = new MyRepository();
        Instance = rep.GetMySingleTon();
      }
    }
    public static MySingleTon Instance { get; private set; }
    public string prop1 { get; set; }
    public string prop2 { get; set; }
  }

ОБНОВЛЕНИЕ: Я делал это очень неправильно.Я думаю, что не нужно ни одного синглтона.Теперь я создал класс со статическими свойствами в третьем проекте, и я устанавливаю его один раз и обращаюсь к нему везде.И это решило мою проблему на данный момент.

Спасибо всем за ваши ответы.

Ответы [ 4 ]

1 голос
/ 30 декабря 2010

Хранилище не должно возвращать одноэлементный объект, а хранилище используется для доступа к данным, а не для возврата одноэлементных объектов.Ваш репозиторий сам по себе может быть одноэлементным, но я не рекомендую его, и я не рекомендую использовать одноэлементный класс для класса, использующего репозиторий.В коде, который у вас есть, создается впечатление, что хранилище должно знать о «бизнес-уровне», который все испортил, отношения должны идти только одним путем.Я бы переписал это как:

public class MySingleTon
{
    private MySingleTon()
    {
       // You constructor logic, maybe create a reference 
       // to your repository if you need it
    }

    private static MySingleTon _instance;
    public static MySingleTon Instance { 
       get
       {
          if(_instance == null)
             _instance = new MySingleTon();
          return _instance;
       }
    }
    public string prop1 { get; set; }
    public string prop2 { get; set; }
}

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

РЕДАКТИРОВАТЬ: Еще одна вещь, почему ваш синглтон имеет несколько общедоступных свойств?Синглтон не должен предоставлять свойства, он должен только представлять функции, и его следует использовать в основном, когда у вас есть служебный класс, такой как Math, или настоящий синглтон, такой как регистратор.

0 голосов
/ 30 декабря 2010

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

Ваш класс MySingleton должен быть скорее неким MyClass, который реализован способом, обычно не зависящим от количества экземпляров, которые будут существовать во время выполнения. Аналогично, MyRepository должен иметь возможность управлять и предоставлять любое количество MyClass экземпляров. Тот факт, что вы будете иметь дело только с единичным экземпляром MyClass, может быть инкапсулирован в отдельный класс фабрики (или метод доступа или как вы его называете), который свяжет MyClass и MyRepository вместе.

Поэтому попробуйте переосмыслить свой дизайн следующим образом (схематично):

public class MyClass { ... }

public class MyRepository
{
    public MyClass GetMyClassInstance(...);
}

public static class MyClassFactory
{
    public static MyClass SingletonInstance 
    { 
        get 
        { 
            if (singletonInstance == null) 
                singletonInstance = myRepository.GetMyClassInstance(...);
            return singletonInstance;
        }
    }
}

Остается вопрос, откуда взялся myRepository. Например, он может быть создан при запуске программы и предоставлен в MyclassFactory как поле участника.

В конце концов, многое можно упростить, если вы решите использовать инверсию контрольного контейнера. Следующим шагом также является переход к проектированию на основе интерфейса. Это дает вам еще один уровень абстракции и обеспечивает большую гибкость в плане взаимозаменяемости реализаций.

0 голосов
/ 30 декабря 2010

в дополнение к коду от Saurabh вы измените класс Singleton на:

public class MySingleTon
  {
    static MySingleTon()
    {
      if (Instance == null)
      {
        Instance = new MySingleTon();
      }
    }

    private MySingleTon(){}

    public static MySingleTon Instance { get; private set; }
    public IMyRepository MyRepository{ get; set ;}

  }
0 голосов
/ 30 декабря 2010

Хотя создание такого класса не очень хорошо, и я не знаю, в чем причина этого.

, но вы можете сделать аналогично приведенному ниже коду

Создатьпроект под названием Public Interface и определите интерфейс IMyRepository с общедоступными функциями, которые вы хотите предоставить из класса MyRepository.

Создайте открытое свойство в классе singleton, которое возвращает IMyRepository и может быть также установлено вне сборки.

Теперь вам нужно явно установить это свойство из сборок, которые ссылаются на вашу сборку singelton, и я предполагаю, что вы можете создать объект класса MyRepository из других сборок.

Обратите внимание: вышеРешение - это всего лишь хитрость для разрыва круговой привязки, а не оптимальное решение.

...