Возможно использовать синглтон с конструктором без декорации в C#?

StackOverflow https://stackoverflow.com/questions/885972

Вопрос

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

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

Себастьян

Это было полезно?

Решение

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

Пример:

Singleton s = Singleton.getInstance(42);

В коде Синглтона:

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

Другие советы

Есть некоторые рамки впрыска в зависимости, такие как Spring.net, которые могут вам помочь. Вы можете эффективно передать параметр в файле конфигурации для своего конструктора Singletons.

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top