我是vb.net的新手,这是我的第一个项目,我相当确定有一个我无法找到的明显答案。
问题:我有一个我用许多属性定义的结构列表。我希望能够在关闭程序并加载备份之后,使用我保存到的值来编辑和加载该列表。做这个的最好方式是什么?
这不是一个简单的字符串或bool,否则我会在项目的属性中使用通常建议的用户设置。我已经看到其他人将它保存为xml并将其恢复原状,但我并不倾向于这样做,因为这将分发给其他人。由于它是一个复杂的结构,通常持有的首选方法是什么?
示例
这是一个结构:
Structure animal
Dim coloring as string
Dim vaccinesUpToDate as Boolean
Dim species as string
Dim age as integer
End structure
并且用户将添加的列表(动物)说1只猫,2只狗等。我想要它,以便在用户添加这些程序后关闭程序,该结构将被保存仍然有那只1只猫和2只狗的设置,所以我可以再次显示它们。在我的程序中保存数据的最佳方法是什么? 谢谢!
答案 0 :(得分:2)
考虑序列化。为此,一个类比旧式的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)”
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
可能是内部的,集合可以保存/加载列表。
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都是相同的语法。对于少量数据,序列化列表是数据库的简单替代(并且具有许多其他用途,例如更好的设置方法)。
请注意,我添加了BirthDate
属性并更改了Age
来计算结果。您不应保存任何可以轻松计算的内容:为了更新Age
(或VaccinesUpToDate
)您必须“访问”每条记录,执行计算然后保存结果 - 可能在24小时内出错了。
将Age
作为属性(而不是函数)公开的原因用于数据绑定。将List<T>
用作DataSource
:
animalsDGV.DataSource = myAnimals
每个动物的结果将是一行,每个属性作为一列。原始Fields
中的Structure
将不会显示。也不会显示Age()
函数,将结果包装为只读属性会显示它。在PropertyGrid
中,它会显示为已停用,因为它是RO。
因此,如果使用Properties的Structure可以工作,为什么要使用Class呢?从Choosing Between Class and Struct on MSDN开始,避免使用结构,除非该类型符合以下所有条件:
Animal
未通过前3个点(虽然它是本地项,但它不是值#1)。它可能也会失败,取决于它的使用方式。