2013-02-19 61 views
5

给出一点背景。将数据保存到.net中的文件时的良好编码实践

我创建了一个应用程序,允许用户保存设置,然后在稍后的日期调用设置。为此,我创建了一些可序列化的对象。我已经得到这个使用BinaryFormatter工作没有太大麻烦。

我开始遇到问题的时候是我升级软件并添加新设置。现在我的可序列化的对象不匹配,所以我必须更新文件。我已经成功完成了几个版本。但要做到这一点,我尝试反序列化文件,如果它引发异常,我尝试下一个版本。 。然后是下一个。 。然后是下一个。 。 。直到我找到合适的人。然后,我必须为每个旧版本编写转换函数,以将其转换为最新版本。我也创建了一个“修订”文件,所以我可以检查他们的版本,然后升级它,但我仍然需要保留许多不同的“版本”,并为它们编写转换函数。 。 。这对我来说本质上是混乱的,如果我继续沿着这条路线走下去,那么容易在后面臃肿。

必须有更好的方法来做到这一点,我只是不知道如何。

感谢

+0

在.net框架中内置了功能,从版本2开始,它完全符合您的需求,而无需编写自己的代码。请参阅下面的答案。 – Andy 2013-02-19 22:57:03

回答

3

你需要写一个serialization binder解决组件。

对于设置,我使用Dictionary<string, byte[]>保存到文件。我序列化字典,一切都很好。当我添加新的设置时,如果在设置文件中找不到,我会提供默认设置。

另外,如果您将字段添加到序列化对象,则可以使用[可选]进行修饰。

0

实际上,这可以通过将[DefaultValue()]属性添加到设置对象上的较新属性来完成 - 至少对于XML序列化来说。我没有尝试过使用二进制序列化。对于xml,这意味着它们是“可选的”,并且在加载旧版本的文件时序列化不会中断。您可以在名称空间System.ComponentModel中找到此属性;

class MySettings 
{ 
    public int MaxNumLogins { get; set; } 

    // specify the value to default to if it's not present in the serialized file... 
    [DefaultValue(0)] 
    public int CacheTimeoutMinutes { get; set; } 
} 
+0

二进制序列化比XML序列化更挑剔,我认为它不会起作用。 – 2013-02-19 22:46:18

0

除了将字段命名为其他人所建议的这种类型的东西,只是为了版本号而大声呼喊。

2

这正是Settings类的用途。您可以在app.config中定义默认值,然后用户可以更改它们,当您保存时,它们的更改将保存到其用户配置文件中的某个位置。当你阅读它们时,你会得到修改的设置。

这个链接是VS 2005,但它的工作原理完全在VS 2012是相同的:http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx

找到的链接,VS2012:http://msdn.microsoft.com/EN-US/library/k4s6c3a0(v=VS.110,d=hv.2).aspx

+0

很高兴知道,谢谢。这不是我所需要的,但我将来可能会使用它。 – EatATaco 2013-02-21 16:08:29

+0

@EatATaco在你的问题中没有任何东西让我觉得你正在做一些内置功能没有提供的东西,所以它看起来像你正在重新发明轮子。也许你可以更新你的问题,所以我们可以知道为什么内置设置不适合这个。 – Andy 2013-02-21 20:57:59

0

你可以看看protobuf网http://code.google.com/p/protobuf-net/wiki/GettingStarted如果你是做二进制,因为所有这些东西都涵盖了版本控制等。它也非常紧凑。它也是积极开发的,如果你使用.proto文件,如果你有潜在的跨平台需求,你也可以实现。

如果您希望人们能够编辑设置(在您的程序之外),那么您可以使用XML *序列化方法。

1

XML格式适用于这种情况。您会在设置文件的早期版本中找到必要的旧设置。甚至旧版本也可以处理从较新版本创建的XML设置。它不能“自动”工作,即使用像Serialize/Deserialize这样的方法,但编写转换函数并不容易或更快。