2010-12-30 3 views
0

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

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; } 
    } 

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

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

+0

Что делает MyRepository точно? Похоже, что он отвечает за возвращение экземпляра MySingleton. Если да, не можете ли вы заменить инициализатор на конструктор или статический метод и перейти в 'this', а не создавать новый репозиторий в MySingleton? –

+0

Почему ты так делаешь? – jason

ответ

1

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

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.

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

0

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

, но вы можете сделать похож на приведенный ниже код

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

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

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

Обратите внимание: выше решение - это всего лишь трюк, чтобы сломать круглую ссылку не оптимальным решением.

0

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

Ваш класс 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

в дополнении к коду из Саурабх, вы измените класс 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 ;} 

    }