通过序列化支持的单例 class
Singleton class backed via serialization
我正在编写单例 class 来访问列表。首次初始化 Singleton 时,通过反序列化 xml 文件填充此列表。
这一切都很好,但我希望这个列表是可更新的,为了做到这一点,我目前每次添加或从中删除时都必须重新序列化。
当对象从内存中移除时,我宁愿只调用一次来序列化列表。但是我觉得在 ~Destructor 中尝试这样做可能会导致数据丢失等。
实现此行为应遵循的最佳模式是什么?
谢谢
C# 中的析构函数are very different from C++ destructors. They are not actual destructors that are run on fully correct objects which are no longer required, but a last resort measure to deal with unmanaged resources (MSDN):
You should override Finalize for a class that uses unmanaged resources
such as file handles or database connections that must be released
when the managed object that uses them is discarded during garbage
collection.
因此使用 Finalizer (Destructor) 与托管资源进行互操作是个坏主意,因为:
The finalizers of two objects are not guaranteed to run in any
specific order, even if one object refers to the other. That is, if
Object A has a reference to Object B and both have finalizers, Object
B might have already been finalized when the finalizer of Object A
starts.
反序列化的数据列表在最终确定期间可能是正确的,或者它可能在之前的 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;
}
}
或者如果您的单例基于它的使用,请使用适当的 Lazy<T>
constructor。
我正在编写单例 class 来访问列表。首次初始化 Singleton 时,通过反序列化 xml 文件填充此列表。
这一切都很好,但我希望这个列表是可更新的,为了做到这一点,我目前每次添加或从中删除时都必须重新序列化。
当对象从内存中移除时,我宁愿只调用一次来序列化列表。但是我觉得在 ~Destructor 中尝试这样做可能会导致数据丢失等。
实现此行为应遵循的最佳模式是什么?
谢谢
C# 中的析构函数are very different from C++ destructors. They are not actual destructors that are run on fully correct objects which are no longer required, but a last resort measure to deal with unmanaged resources (MSDN):
You should override Finalize for a class that uses unmanaged resources such as file handles or database connections that must be released when the managed object that uses them is discarded during garbage collection.
因此使用 Finalizer (Destructor) 与托管资源进行互操作是个坏主意,因为:
The finalizers of two objects are not guaranteed to run in any specific order, even if one object refers to the other. That is, if Object A has a reference to Object B and both have finalizers, Object B might have already been finalized when the finalizer of Object A starts.
反序列化的数据列表在最终确定期间可能是正确的,或者它可能在之前的 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;
}
}
或者如果您的单例基于它的使用,请使用适当的 Lazy<T>
constructor。