Singleton类通过序列化支持

时间:2015-04-10 17:06:31

标签: c# windows serialization singleton

我正在编写Singleton类来访问List。首次初始化Singleton时,将通过反序列化xml文件来填充此List。

这一切都很好但我希望这个List可以更新,为了做到这一点,我每次添加或删除时都要重新序列化。

当从内存中删除对象时,我宁愿只调用一次序列化列表。但是我觉得在~Destructor中尝试这样做可能会导致数据丢失等。

实现此行为的最佳模式是什么?

由于

1 个答案:

答案 0 :(得分:2)

来自C ++析构函数的C#are very different中的析构函数。它们不是在不再需要的完全正确的对象上运行的实际析构函数,而是处理非托管资源的最后手段(MSDN):

  

您应该为使用非托管资源的类重写Finalize   例如必须释放的文件句柄或数据库连接   当在垃圾中丢弃使用它们的托管对象时   集合。

因此,使用Finalizer (Destructor)与托管资源进行互操作是一个坏主意,因为:

  

两个对象的终结器不能保证在任何对象中运行   特定顺序,即使一个对象引用另一个对象。也就是说,如果   对象A具有对象B的引用,并且都具有终结符Object   在对象A的终结器时,B可能已经完成   启动。

反序列化数据列表在此类最终确定期间可能是正确的,或者在之前的GC运行期间可能已经回收。即使现在的垃圾收集器不是这样,也没有人能保证这个问题不会出现在下一个.NET版本中。在Finalizer中访问托管资源实际上是一种未定义的行为。

可能的解决方案

考虑到你的对象是单例,因此只有在应用程序退出时才会被垃圾收集(或者永远不会被请求), 允许此类持久存储对象数据的最简单方法是将事件处理程序附加到application close(exit) event

...
public static Singleton Instance
{
     get
     {
         if (_Instance == null)         
         {
             _Instance = new Singleton();
             Application.Exit += (sender, args) =>
             {
                 _Instance.SaveChanges();
             }
         }

         return _Instance;
     }
}

如果您的Singleton基于其使用,则使用适当的Lazy<T> constructor