Вопросы о правилах синглтона (не позволяют создавать копии и десериализацию) - PullRequest
3 голосов
/ 28 апреля 2010

Читая какую-то статью о синглтоне, я остановился на том, что сказал: «Не позволяйте создавать копии существующего экземпляра».Я понял, что я не знаю, как бы я это сделал!Подскажите, пожалуйста, как я могу скопировать существующий экземпляр класса?И второе: десериализация.Чем это может быть опасно?

И для обоих - как запретить создание копий или десериализацию?Спасибо

Ответы [ 4 ]

3 голосов
/ 28 апреля 2010

Используя сериализацию / десериализацию, вы можете где-то сохранить объект, а затем восстановить его. Таким образом, у вас будет два объекта. Любые изменения, внесенные в синглтон за это время, не будут отражены в вашей новой копии.

Впоследствии, когда вы сейчас пытаетесь получить / установить что-то с помощью одноэлементного объекта, вы можете изменить его / получить от одного объекта или другого. Очевидно, что это может вызвать всевозможные (иногда очень сложные для отладки) проблемы.

РЕДАКТИРОВАТЬ: Чтобы создать синглтон в C #, см. Объяснение на http://www.yoda.arachsys.com/csharp/singleton.html

Что касается сериализации: вы должны явно включить ее, включив SerializableAttribute . Так что просто не отмечайте свой класс этим. Обратите внимание, что нет NonSerializableAttribute для классов, только для полей. Он используется, когда вы включили сериализацию, но хотите запретить ее для определенных частей класса.

EDIT2: чтобы запретить XML-сериализацию, вы можете реализовать IXmlSerializable для класса. Тогда просто либо имейте пустые реализации, либо бросайте исключения из методов-членов.

3 голосов
/ 28 апреля 2010

Существуют объекты с чем-то вроде метода Clone или Copy. За этим стоит идея, что он возьмет текущие значения объекта и создаст новое. Поражает цель объекта-одиночки, потому что вдруг кто-то может создать его вторую копию.

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

2 голосов
/ 28 апреля 2010

Есть несколько вещей, на которые стоит обратить внимание, например, Кевин упомянул любой метод .Clone() или .Copy(). Если вы строите класс сами, то будьте осторожны с методом .MemberwiseClone(), так как он будет делать мелкие копии объекта.

Что касается сериализации. Предотвратить общую сериализацию можно, не помечая [SerializableAttribute()] своим классом. Я не уверен, что есть способ предотвратить XmlSerialization напрямую. Но есть несколько вещей, которые вы могли бы сделать, чтобы предотвратить это, если бы вы строили класс.

Если вы создаете класс и не предоставляете конструктор по умолчанию, XmlDeserializer не будет работать, поскольку он использует конструктор по умолчанию для перестройки объекта. Однако я верю, что эта функциональность изменилась в 4.0, так что, возможно, вы захотите больше в этом разобраться. Использование атрибута [XmlIgnore] для полей и свойств yoru также сделает сериализацию бесполезной.

Важной частью здесь является то, что человек, пытающийся сделать это, понимает, что это не должно быть сделано, не то, что это не может. Если кто-то действительно хочет выполнить сериализацию / десериализацию в вашем классе, то вы не можете остановить все возможности, поскольку он может реализовать свою собственную сериализацию / десериализацию вашего объекта. Также иногда подразумевается сериализация синглетонов, например, в случае настроек приложения или пользовательских настроек. Намерение состоит в том, чтобы как-то проинформировать человека, пытающегося сериализоваться / десериализоваться, об этом.

2 голосов
/ 28 апреля 2010

Как уже упоминалось:

Вы не хотите делать сериализуемый синглтон или копируемый / клонируемый, потому что тогда вы можете создать более одного объекта, который противоречит цели синглтона.

Легко предотвратить сериализацию в c # - не помечайте класс как [Serializable]

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

Другой способ (вероятно, лучше) подробно описан в пункте 13 «Эффективного C #» Билла Вагнера. то есть используя статический конструктор и делая ваш синглтон доступным только для чтения свой статический класс.

Пример:

public class SingletonExample
{
    private static readonly SingletonExample singleInstance
    static SingletonExample()
    {
        singleInstance = new SingletonExample();
    }
    public static SingletonExample Instance
    {
        get { return singleInstance; }
    }
    private SingletonExample()
    {
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...