在 C# 中是否有更好的序列化对象的方法?
我的一位同事要求我将这段代码放在这里,看看是否有人能想出更好的方法来做到这一点。
有两种方法可以从光盘序列化和加载对象。加载使用通用参数来指定正在加载的对象的类型。
public static class IO
{
public static void SaveObject(string path, object obj)
{
using (Stream stream = File.Open(path, FileMode.Create))
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
}
}
public static T LoadObject<T>(string path)
{
using (Stream stream = File.Open(path, FileMode.Open))
{
IFormatter formatter = new BinaryFormatter();
T obj = (T)formatter.Deserialize(stream);
return obj;
}
}
}
One of my colleagues challenged me to put this code up here to see if anyone can think of a better way of doing this.
It's two methods to serialize and load objects from disc. The load uses a generic parameter to specify the type of object that is being loaded.
public static class IO
{
public static void SaveObject(string path, object obj)
{
using (Stream stream = File.Open(path, FileMode.Create))
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
}
}
public static T LoadObject<T>(string path)
{
using (Stream stream = File.Open(path, FileMode.Open))
{
IFormatter formatter = new BinaryFormatter();
T obj = (T)formatter.Deserialize(stream);
return obj;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我更改了方法名称以反映它们的用途。
Load
并没有真正说明它们的作用。Serialize 方法现在是一种扩展方法。
我添加了一个检查来查看对象类型是否可以序列化。
FormatWith 扩展方法可以更轻松地处理字符串格式:
I've change the method names to reflect what they to.
Load
doesnt really say what they do.The serialize method is now an extension method.
I've added a check to see if the object type can be serialized.
The FormatWith extension method makes it easier to work with string formatting:
序列化是类的一个方面,通常被视为正交 - 这意味着类应该对此几乎一无所知。 “几乎”是因为在某些情况下,对象不应被序列化(如代理)或具有不应序列化的成员。
为此,发明了序列化属性 -
Type
类上甚至有一个IsSerialized
属性。通过这种方式,您的方法已经非常好,因为对象除了使用属性之外不必执行任何操作即可序列化。不好的是你只能在运行时捕获错误,而不能在编译时捕获错误。您可以采取一些保护措施,例如ISerialized
标记接口,并向您的IO
类添加类型限制,但这可能是不可能的(第 3 方库)或很多努力(改变所有课程)。您甚至可以走那么远,将序列化卸载到对象,以便它们确切地知道如何反/序列化,但我怀疑这是值得的,而您应该能够通过单元测试捕获大多数运行时问题。我看到的唯一真正的问题是,您可能会反序列化
B
类型的对象,而实际上您正在尝试反序列化A
类型。现在我想说,序列化程序抛出无效的强制转换异常或在完成之前知道您正在反序列化错误的类型没有什么区别 - 在这两种情况下,您都会遇到问题,并且您的应用程序无法执行其应有的操作。您可以使用 自定义序列化绑定器 或者您可能需要考虑 xml 序列化程序。
Well serialization is an aspect to the classes which is usually treated orthogonal - meaning the classes should know almost nothing about it. "Almost" because you have cases where objects should not be serialized (like proxies) or have members which should not be serialized.
For this the serialization attributes where invented - there is even an
IsSerializable
property on theType
class. In that way your approach is already very good in the sense that objects don't have to do anything to be serialized except using the attributes. The bad thing is that you only catch errors at runtime and not compile time. You could put some safeguards in place like anISerializable
marker interface and add a type restriction to yourIO
class but that might not be possible (3rd party libs) or a lot of effort (changing all classes around). You could even go that far to offload the serialization to the objects so they know exactly how to de/serialize but I doubt it's worth the effort whereas you should be able to catch most runtime problems with unit tests.The only real problem I can see is that you might deserialize an object of type
B
where as you are actually trying to deserialize typeA
. Now I would say there is no difference to your serializer throwing an invalid cast exception or knowing that you are deserializing the wrong type before you have finished - in both cases you have a problem and your application can't do what it's supposed to.You can get around version problems with the
BinaryFormatter
with a custom serialization binder or you might want to consider a xml serializer.根据您想要序列化的对象类型,不同的序列化程序可能会更优化。例如,
ObjectStateFormatter
经过优化,可以序列化和格式化许多常见的 .NET Framework 引用类型。Depending on what kind of object you want to serialize, a different serializer might be more optimized. For example the
ObjectStateFormatter
is optimized to serialize and format many common .NET Framework reference types.BinaryFormatter 还会序列化定义类型的程序集版本,并且在加载另一个版本进行反序列化时会失败(如果我没记错的话)。这意味着如果仅序列化数据,您应该能够使用更少的空间来存储它。
您可以在序列化对象时检查结果,并考虑“更好”的方式来存储信息,但大多数替代方案的做法也略有不同(功能上)。
The
BinaryFormatter
also serializes the assembly version the type was defined in, and fails (if I remember correctly) when deserialized with another version loaded. This means that if serializing the data only, you should be able to store it using less space.You could inspect the result when serializing an object, and think of "better" ways to store information, but most alternatives also do things slightly different (functionally).