Можно использовать синглтон с конструктором не по умолчанию в C #? - PullRequest
3 голосов
/ 20 мая 2009

Я внедряю платформу уведомлений для одного из моих проектов. Поскольку я хочу, чтобы он был очень общим, пользователь может использовать несколько транспортных уровней, так что ему не нужно заботиться об использовании одного метода доставки (скажем, WCF) или другого (например, ActiveMQ). Интерфейс, к которому пользователь имеет доступ, конечно, не зависит от метода доставки (WCF или ActiveMQ). Тем не менее, два класса (потребитель и производитель) реализуют синглтоны, поэтому они фактически используют конструкторы по умолчанию (то есть без параметров). Моя проблема в том, что я хотел бы иметь один параметр, метод доставки, который пользователь хочет использовать. Но насколько я знаю, синглтон использует только конструкторы по умолчанию? это нормально, так как не должно быть смысла использовать синглтоны с параметрами. Итак, какие у меня есть варианты? не создавать синглтон? создать метод для установки метода доставки?

Большое спасибо за помощь,

Себастьян

Ответы [ 4 ]

5 голосов
/ 20 мая 2009

У вас могут быть параметры с синглетами, за исключением того, что вместо передачи параметра в конструктор вы передаете его в метод getInstance (). Разумеется, ваш переопределенный конструктор должен быть закрытым для настоящей одноэлементной реализации. Мой пример написан на Java, но применим и к C #.

Пример:

Singleton s = Singleton.getInstance(42);

В коде Singleton:

private Singleton() {

}

private Singleton(int num) {
   //set num
}

public getInstance(int num) {
  //singleton code (calls the private non-default constructor if an object 
  //does not already exist) 
}
0 голосов
/ 02 февраля 2012

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

public void Init(/*parameters*/)
{
        if (_isInitialized)
        {
            throw new InvalidOperationException("Component is already initialized!");
        }
        //do your work here
}

Любой другой доступ к экземпляру синглтона (свойства get, set, вызовы методов) вызовет недопустимое исключение операции, сообщающее, что объект не был инициализирован.

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

0 голосов
/ 20 мая 2009

Вы можете легко сделать это с помощью структуры внедрения зависимостей. У меня есть аналогичная конструкция в моем текущем проекте, используя MEF . Все, что требуется, - это использовать параметры внедрения конструктора и добавить эту сборку и сборку запрошенной зависимости в каталог, и она правильно подключится.

Другой вариант - использовать функцию инициализации, которая принимает ваш вариант и создает экземпляр singleton. Вместо того чтобы создавать его при первом доступе, вы можете создать его во время вызова инициализации. Недостатком здесь является то, что вам нужно обязательно инициализировать ваш синглтон перед его использованием (обычно при запуске программы, используя файл конфигурации).

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

0 голосов
/ 20 мая 2009

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

Ссылка на пример Spring Framework

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

...