为什么单身人士无法直接实现IObjectReference?

黑暗泰格

每当有人问如何在C#中实现可序列化的单例时,基本建议始终是实现ISerializable,然后在GetObjectData中将类型设置为实现IObjectReference的帮助程序类型。然后应该使用该类型的GetRealObject函数返回单例实例。

这实际上是在此页面上的示例代码中完成的方式:https : //msdn.microsoft.com/en-us/library/system.runtime.serialization.iobjectreference.aspx

我的问题是,为什么没有人建议单例本身实现IObjectReference?在某些情况下不应该工作吗?

考虑一下,例如:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

class Program {
    // Works:
    [Serializable]
    class Singleton1 : ISerializable {
        public static readonly Singleton1 instance = new Singleton1();

        private Singleton1() {
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context) {
            info.SetType(typeof(Helper));
        }

        [Serializable]
        private class Helper : IObjectReference {
            public object GetRealObject(StreamingContext context) {
                return instance;
            }
        }
    }

    // Works:
    [Serializable]
    class Singleton2 : IObjectReference {
        public static readonly Singleton2 instance = new Singleton2();

        private Singleton2() {
        }

        public object GetRealObject(StreamingContext context) {
            return instance;
        }
    }

    // Does not work, of course:
    [Serializable]
    class Singleton3 {
        public static readonly Singleton3 instance = new Singleton3();

        private Singleton3() {
        }
    }

    static void Main(string[] args) {
        Console.WriteLine("Testing Singleton1");
        TestSingleton(Singleton1.instance);

        Console.WriteLine("Testing Singleton2");
        TestSingleton(Singleton2.instance);

        Console.WriteLine("Testing Singleton3, expect to fail.");
        TestSingleton(Singleton3.instance);
    }

    static void TestSingleton(object singletonInstance) {
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        MemoryStream memoryStream = new MemoryStream();

        binaryFormatter.Serialize(memoryStream, singletonInstance);

        memoryStream.Position = 0;
        object newInstance = binaryFormatter.Deserialize(memoryStream);

        bool shouldBeTrue = object.ReferenceEquals(singletonInstance, newInstance);
        Debug.Assert(shouldBeTrue);
    }
}

Singleton1以通常推荐的方式实现。Singleton2直接实现IObjectReference。当然,Singleton3并没有做任何特别的事情并且失败了。

我从未见过有人建议像上面的Singleton2那样做。这是为什么?

如果我不得不猜测,可能会是以下两件事之一:

  1. 可能是因为它在某些情况下会失败。从理论上讲,它将来可能会由于某种原因而失败吗?
  2. 可能是因为第二个实例确实在框架调用GetRealObject之前短暂存在。但是可以肯定的是,这段时间并不重要,对吧?
数据库

可能是因为反序列化“真实”单例类型的实例将需要暂时存在一个以上的单例实例,这将违反其基本设计原理。

由于单例通常很重,因此这样做可能会导致实际问题。例如,如果单例在其构造函数中打开文件以缓存内容,则第二个临时单例可能会尝试第二次打开同一文件,从而导致异常。

在使用进行序列化的特定情况下,序列BinaryFormatter化“真实”单例将导致其所有内部状态都被序列化(即所有公共字段和私有字段)。可能不是期望的,因为单例通常代表全局会话状态而不是模型状态。避免内部状态的序列化将要求标记所有字段,[NonSerialized]这些字段可能会成为容易被忽视的麻烦。

可能是您的特定单身人士没有上述任何问题,但其他人可能没有,因此官方建议不建议这样做。相反,建议您使用更复杂的设计模式,以便您可以简化自己,只要您已确认这样做不会导致上述问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么有角度的服务单身人士?

来自分类Dev

为什么有角度的服务单身人士?

来自分类Dev

为什么泽西岛导致单身人士班不上班?

来自分类Dev

单身人士无法正常工作

来自分类Dev

单身人士班无法进入的私人成员

来自分类Dev

匕首2单身人士无法正常工作

来自分类Dev

configatron单身人士?为什么我不能在课堂上访问configatron

来自分类Dev

C ++为什么我的单身人士不保持会员价值

来自分类Dev

为什么在尝试使用Mockito或PowerMock模拟单身人士时不抛出任何异常?

来自分类Dev

单身人士服务

来自分类Dev

斯威夫特单身人士

来自分类Dev

超越主要的单身人士

来自分类Dev

目标C单身人士

来自分类Dev

单身人士并不是真正的单身人士

来自分类Dev

单身人士班不上课

来自分类Dev

设置Ninject单身人士的方法

来自分类Dev

用Mockito模拟单身人士

来自分类Dev

单身人士班不上课

来自分类Dev

单身人士和比赛条件

来自分类Dev

单身人士陷入无限循环

来自分类Dev

使用Spring的泽西岛单身人士:无法将方法强制转换为构造方法

来自分类Dev

如何在Swift中销毁单身人士

来自分类Dev

我应该对单身人士使用改造吗?

来自分类Dev

Laravel 5-单身人士的预期位置

来自分类Dev

有效的单身人士班?

来自分类Dev

是否有必要保存单身人士?

来自分类Dev

我是否过度使用Spring单身人士?

来自分类Dev

单身人士在Rails中的请求范围

来自分类Dev

有效的单身人士班?