问题描述
我是 vb.net 的新手,这是我的第一个项目,我相当肯定有一个我找不到的明显答案.
I am new to vb.net, and this is my first project where I'm fairly certain there is an obvious answer that I just can't find.
问题: 我有一个结构的列表,我定义了许多属性.我希望能够在关闭程序并加载备份后,使用我事先保存的值来编辑和加载该列表.做这个的最好方式是什么?
Problem: I have a list of a structure I have defined with many properties. I want to be able to edit and load that list with the values I have saved to it before hand after closing the program and loading it backup. What is the best way to do this?
这不是简单的字符串或布尔值,否则我将使用项目属性中通常建议的用户设置.我已经看到其他人将其保存到 xml 中并将其取回,但我不倾向于这样做,因为这将被大量分发给其他人.既然它是一个复杂的结构,那么普遍持有的首选方法是什么?
This isn't a simple string or bool, otherwise I would use the user settings that is commonly suggested, in the project's properties. I've seen others that save it into an xml and take it back up, but I'm not inclined to do so since this is going to be distributed to others in mass. Since it's a complex structure, what's the commonly held preferred method?
示例
这是一个结构:
Structure animal
Dim coloring as string
Dim vaccinesUpToDate as Boolean
Dim species as string
Dim age as integer
End structure
并且有一个列表(动物),用户将添加说 1 只猫、2 只狗等.我想要它,以便在用户添加这些后关闭程序后,该结构将被保存为仍然具有具有这些设置的 1 只猫和 2 只狗,以便我可以再次显示它们.在我的程序中保存数据的最佳方法是什么?谢谢!
And there's a List(Of animal) that the user will add say 1 cat, 2 dogs, etc. I want it so that once the programs is closed after the user has added these, that structure will be saved to still have that 1 cat and 2 dogs with those settings so I can display them again. What's the best way to save the data in my program?Thanks!
推荐答案
考虑序列化.为此,类比老式的结构更有序:
Consider serialization. For this, a class is more in order than an old fashioned Struct:
<Serializable>
Class Animal
Public Property Name As String
Public Property Coloring As String
Public Property VaccinesUpToDate As Boolean
Public Property Species As String
Public Property DateOfBirth As DateTime
Public ReadOnly Property Age As Integer
Get
If DateOfBirth <> DateTime.MinValue Then
Return (DateTime.Now.Year - DateOfBirth.Year)
Else
Return 0 ' unknown
End If
End Get
End Property
' many serializers require a simple CTor
Public Sub New()
End Sub
Public Overrides Function ToString() As String
Return String.Format("{0} ({1}, {2})", Name, Species, Age)
End Function
End Class
ToString()
覆盖很重要.如果您将 Animal
对象添加到 ListBox
将显示的内容,例如:Stripe (Gremlin, 27)"
The ToString()
override can be important. It is what will display if you add Animal
objects to a ListBox
e.g.: "Stripe (Gremlin, 27)"
Friend animalList As New List(of Animal) ' a place to store animals
' create an animal
a = New Animal
a.Coloring = "Orange"
a.Species = "Feline" ' should be an Enum maybe
a.Name = "Ziggy"
a.BirthDate = #2/11/2010#
animalList.Add(a)
' animalList(0) is now the Ziggy record. add as many as you like.
在更复杂的应用程序中,您可能会编写一个 Animals
集合类.在这种情况下,List
可能是内部的,集合可以保存/加载列表.
In more complex apps, you might write an Animals
collection class. In that case, the List
might be internal and the collection could save/load the list.
Friend Sub SaveData(fileName as String)
Using fs As New System.IO.FileStream(fileName,
IO.FileMode.OpenOrCreate)
Dim bf As New BinaryFormatter
bf.Serialize(fs, animalList)
End Using
End Sub
Friend Function LoadData(fileName as String) As List(Of Animal)
Dim a As List(of Animal)
Using fs As New FileStream(fileName, FileMode.Open, FileAccess.Read)
Dim bf As New BinaryFormatter
a = CType(bf.Deserialize(fs), List(Of Animal))
End Using
Return a
End Function
XMLSerialization、ProtoBuf 甚至 json 的语法都差不多.对于少量数据,序列化列表是数据库的简单替代方案(并且还有许多其他用途,例如更好的设置方法).
XMLSerialization, ProtoBuf and even json are much the same syntax. For a small amount of data, a serialized list is an easy alternative to a database (and have many, many other uses, like a better Settings approach).
请注意,我添加了 BirthDate
属性并更改了 Age
以计算结果.您不应该保存任何易于计算的内容:为了更新 Age
(或 VaccinesUpToDate
),您必须访问"每条记录,然后执行计算保存结果 - 24 小时内可能会出错.
Notice that I added a BirthDate
property and changed Age
to calculate the result. You should not save anything which can be easily calculated: in order to update the Age
(or VaccinesUpToDate
) you'd have to 'visit' each record, perform a calculation then save the result - which might be wrong in 24 hours.
将 Age
作为属性(而不是函数)公开的原因是为了数据绑定.使用 List
作为 DataSource
是很常见的:
The reason for exposing Age
as a Property (rather than a function) is for data binding. It is very common to use a List<T>
as the DataSource
:
animalsDGV.DataSource = myAnimals
结果将是每个动物的一行,每个属性作为一列.Fields
不会出现在原始 Structure
中.Age()
函数也不会显示,将结果包装为只读属性来显示它.在 PropertyGrid
中,它会显示为禁用,因为它是 RO.
The result will be a row for each animal with each Property as a column. Fields
as in the original Structure
won't show up. Nor would an Age()
function display, wrapping the result as a readonly property displays it. In a PropertyGrid
, it will show disabled because it is RO.
那么如果使用属性的结构可以工作,为什么要使用类呢?从 在 MSDN 上选择类和结构,避免 使用结构,除非类型满足以下所有条件:
So if a Structure using Properties will work, why use a Class instead? From Choosing Between Class and Struct on MSDN, avoid using a Structure unless the type meets all of the following:
- 它在逻辑上表示单个值,类似于原始类型(int、double 等)
- 它的实例大小低于 16 字节
- 它是不可变的
- 不必经常装箱
Animal
未通过前 3 分(虽然它是本地 item,但它不是 #1 的 value).取决于它的使用方式,它也可能最后失败.
Animal
fails the first 3 points (while it is a local item it is not a value for #1). It may also fail the last depending on how it is used.
这篇关于.exe 关闭后如何在 vb.net 中保存/重新加载数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!