VB.Net My.Settings 已保存 SQL 服务器列表的自定义类型
VB.Net My.Settings custom type for list of saved SQL servers
我正在尝试使用 My.Settings 来保存经过身份验证的服务器及其信息的列表,但我无法弄清楚如何制作我的自定义类型。
我现在有一个名为 SqlServer 的 class,它具有以下三个字段:
Public ServerName As String
Public UserName As String
Public Password As String
每次我使用 SQL 身份验证连接到 SQL 服务器时,我想保存该服务器和登录信息。这意味着我需要一个自定义类型,它是 My.Settings 中 SqlServer 的集合。
这是我目前的代码:
Public Class SQLServerList
Inherits List(Of SQLServer)
Implements IComparable(Of SQLServer)
Public Function CompareTo(ByVal SqlServerInfo As SQLServer) As Integer Implements IComparable(Of MyProjectName.SQLServer).CompareTo
...
End Function
End Class
我继承 List 的方向是否正确?我需要什么样的 properties/fields 才能让这个东西按我想要的方式运行?谢谢。
如果你想保存一些你定义的 class 到 My.Settings 你基本上需要满足与任何 XML-serializable class.
- 您的 class 必须是可序列化的。
- 您的 class 必须有一个 public 不带参数的默认构造函数。
- 您 class 中任何来自 .NET 的类型的 属性 都必须是可序列化的。
- 您的 class 中包含的任何 class 都必须满足这些相同的要求。
给定一个集合 class,很容易让它自己序列化内容。
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
<Serializable>
Public Class Server
Public Property Name As String
Public Property UserName As String
Public Property Password As String
End Class
一个简单的合集class:
<Serializable>
Public Class Servers
Private myList As List(Of Server)
Public Sub New()
myList = New List(Of Server)
End Sub
Public Sub Add(svr As Server)
myList.Add(svr)
End Sub
' no reason it cant also create server objects for you
Public Sub Add(sname As String, uname As String, pw As String)
myList.Add(New Server With {.Name = sname, .UserName = uname, .Password = pw})
End Sub
'toDo Contains, Count, Item etc as needed
Public Sub Save(mypath As String)
Using fs As New FileStream(mypath, FileMode.OpenOrCreate)
Dim bf As New BinaryFormatter
bf.Serialize(fs, myList)
End Using
End Sub
Public Function Load(mypath As String) As Int32
'ToDo: check if file exists
Using fs As New FileStream(mypath, FileMode.Open)
Dim bf As New BinaryFormatter
myList = CType(bf.Deserialize(fs), List(Of Server))
End Using
If myList IsNot Nothing Then
Return myList.Count
Else
Return 0
End If
End Function
End Class
BinaryFormatter
需要 <Serializable>
属性。不同的序列化器(json、ProtoBuf-NET)可能有自己的序列化器。
"magic" 在 Save
和 Load
方法中,它们序列化或反序列化对象的内部列表。只需几行代码即可 load/save 1 或 1000 个项目。对于少量数据,它是数据库的绝佳替代品。
正在测试往返:
Dim svrs As New Servers
svrs.Add("SqlSS1", "ziggy", "foo")
svrs.Add("SqlSS2", "zacky", "bar")
svrs.Add("SqlSS3", "zoey", "baz")
svrs.Save("C:\Temp\SSvrs.bin")
' now load to a new Servers collection
' to test the round trip
Dim svrs2 As New Servers
Dim sCount = svrs2.Load("C:\Temp\SSvrs.bin")
For n = 0 To sCount - 1
Console.WriteLine("{0} {1} {2} ", svrs2(n).Name, svrs2(n).UserName, svrs2(n).Password)
Next
输出:
SqlSS1 ziggy foo
SqlSS2 zacky bar
SqlSS3 zoey baz
我使用了 BinaryFormatter(没有真正原因),但 ProtoBuf-NET 或 XMLSerializer 也可以。由于数据都是字符串,您可能希望对它们进行加密(将文件流包装在密码流中)。
基准测试,将对象序列化为二进制文件、XML文件和XML字符串:
- 将 500.000 个对象写入二进制文件(1954 毫秒/23MB)
- 将 500.000 个对象写入 XML 文件(660 毫秒/46MB)
- 将 500.000 个对象写入 XML-字符串(847 毫秒,进程 38MB->348MB)
惊讶地发现写入二进制文件比 XML 文件花费的时间更长。我希望 .Net 只是将内存转储到文件而不进行任何处理和转换。也许有比使用的更好的二进制序列化程序?
虽然预计会更小。 XML 文件 "only" 的开销为 100%。
看到写入 XML 文件比写入内存中的字符串更快也令人惊讶。
我确定我的代码可以优化,因为它很奇怪,请随意贡献:-)
要序列化的对象:
<Serializable> _
Public Class oNames
Public Shared cNames As New List(Of oName)
<Serializable> _
Public Class oName
Public Property Firstname As String
Public Property Lastname As String
Sub New()
End Sub
End Class
Sub New()
End Sub
End Class
用 500.000 个对象填充列表:
oNames.cNames.Clear()
For i As Integer = 1 To 500000
oNames.cNames.Add(New oNames.oName With {.Firstname = "MyFirstName" & i.ToString, .Lastname = "MyLastName" & i.ToString})
Next
写入二进制文件(使用我自己的序列化器class):
WCC.BinSerialization.ToFile(oNames.cNames, "c:\temp\ObjToBin.bin", IO.FileMode.Append)
写入XML文件(使用我自己的序列化器class):
WCC.XMLSerialization.Obj_To_XMLFile(oNames.cNames, "c:\temp\ObjToXML.xml")
写入XML-string(使用我自己的序列化器class):
Dim XMLStr As String
XMLStr = WCC.XMLSerialization.Obj_To_XLMStr(oNames.cNames)
我的序列化器class:
Public Class WCC
Public Class XMLSerialization
Public Shared Function Obj_To_XLMStr(Obj As Object) As String
Using SW As New System.IO.StringWriter
Dim X As New System.Xml.Serialization.XmlSerializer(Obj.GetType)
X.Serialize(SW, Obj)
Return SW.ToString
End Using
End Function
Public Shared Sub XMLStr_To_Obj(XMLString As String, ByRef ListObj As Object)
Using SR As New System.IO.StringReader(XMLString)
Dim X As New System.Xml.Serialization.XmlSerializer(ListObj.GetType)
ListObj = X.Deserialize(SR)
End Using
End Sub
Public Shared Sub Obj_To_XMLFile(Obj As Object, Path As String)
Dim XWS As New System.Xml.XmlWriterSettings
XWS.Indent = True
XWS.IndentChars = vbTab
Using XW As System.Xml.XmlWriter = System.Xml.XmlWriter.Create(Path, XWS)
Dim X As New System.Xml.Serialization.XmlSerializer(Obj.GetType)
X.Serialize(XW, Obj)
End Using
End Sub
End Class
Public Class BinSerialization
Public Shared Sub ToFile(Obj As Object, Path As String, FileMode As IO.FileMode)
Using fs As New System.IO.FileStream(Path, FileMode)
Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
bf.Serialize(fs, Obj)
End Using
End Sub
End Class
End Class
我正在尝试使用 My.Settings 来保存经过身份验证的服务器及其信息的列表,但我无法弄清楚如何制作我的自定义类型。
我现在有一个名为 SqlServer 的 class,它具有以下三个字段:
Public ServerName As String
Public UserName As String
Public Password As String
每次我使用 SQL 身份验证连接到 SQL 服务器时,我想保存该服务器和登录信息。这意味着我需要一个自定义类型,它是 My.Settings 中 SqlServer 的集合。
这是我目前的代码:
Public Class SQLServerList
Inherits List(Of SQLServer)
Implements IComparable(Of SQLServer)
Public Function CompareTo(ByVal SqlServerInfo As SQLServer) As Integer Implements IComparable(Of MyProjectName.SQLServer).CompareTo
...
End Function
End Class
我继承 List 的方向是否正确?我需要什么样的 properties/fields 才能让这个东西按我想要的方式运行?谢谢。
如果你想保存一些你定义的 class 到 My.Settings 你基本上需要满足与任何 XML-serializable class.
- 您的 class 必须是可序列化的。
- 您的 class 必须有一个 public 不带参数的默认构造函数。
- 您 class 中任何来自 .NET 的类型的 属性 都必须是可序列化的。
- 您的 class 中包含的任何 class 都必须满足这些相同的要求。
给定一个集合 class,很容易让它自己序列化内容。
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
<Serializable>
Public Class Server
Public Property Name As String
Public Property UserName As String
Public Property Password As String
End Class
一个简单的合集class:
<Serializable>
Public Class Servers
Private myList As List(Of Server)
Public Sub New()
myList = New List(Of Server)
End Sub
Public Sub Add(svr As Server)
myList.Add(svr)
End Sub
' no reason it cant also create server objects for you
Public Sub Add(sname As String, uname As String, pw As String)
myList.Add(New Server With {.Name = sname, .UserName = uname, .Password = pw})
End Sub
'toDo Contains, Count, Item etc as needed
Public Sub Save(mypath As String)
Using fs As New FileStream(mypath, FileMode.OpenOrCreate)
Dim bf As New BinaryFormatter
bf.Serialize(fs, myList)
End Using
End Sub
Public Function Load(mypath As String) As Int32
'ToDo: check if file exists
Using fs As New FileStream(mypath, FileMode.Open)
Dim bf As New BinaryFormatter
myList = CType(bf.Deserialize(fs), List(Of Server))
End Using
If myList IsNot Nothing Then
Return myList.Count
Else
Return 0
End If
End Function
End Class
BinaryFormatter
需要 <Serializable>
属性。不同的序列化器(json、ProtoBuf-NET)可能有自己的序列化器。
"magic" 在 Save
和 Load
方法中,它们序列化或反序列化对象的内部列表。只需几行代码即可 load/save 1 或 1000 个项目。对于少量数据,它是数据库的绝佳替代品。
正在测试往返:
Dim svrs As New Servers
svrs.Add("SqlSS1", "ziggy", "foo")
svrs.Add("SqlSS2", "zacky", "bar")
svrs.Add("SqlSS3", "zoey", "baz")
svrs.Save("C:\Temp\SSvrs.bin")
' now load to a new Servers collection
' to test the round trip
Dim svrs2 As New Servers
Dim sCount = svrs2.Load("C:\Temp\SSvrs.bin")
For n = 0 To sCount - 1
Console.WriteLine("{0} {1} {2} ", svrs2(n).Name, svrs2(n).UserName, svrs2(n).Password)
Next
输出:
SqlSS1 ziggy foo
SqlSS2 zacky bar
SqlSS3 zoey baz
我使用了 BinaryFormatter(没有真正原因),但 ProtoBuf-NET 或 XMLSerializer 也可以。由于数据都是字符串,您可能希望对它们进行加密(将文件流包装在密码流中)。
基准测试,将对象序列化为二进制文件、XML文件和XML字符串:
- 将 500.000 个对象写入二进制文件(1954 毫秒/23MB)
- 将 500.000 个对象写入 XML 文件(660 毫秒/46MB)
- 将 500.000 个对象写入 XML-字符串(847 毫秒,进程 38MB->348MB)
惊讶地发现写入二进制文件比 XML 文件花费的时间更长。我希望 .Net 只是将内存转储到文件而不进行任何处理和转换。也许有比使用的更好的二进制序列化程序?
虽然预计会更小。 XML 文件 "only" 的开销为 100%。
看到写入 XML 文件比写入内存中的字符串更快也令人惊讶。
我确定我的代码可以优化,因为它很奇怪,请随意贡献:-)
要序列化的对象:
<Serializable> _
Public Class oNames
Public Shared cNames As New List(Of oName)
<Serializable> _
Public Class oName
Public Property Firstname As String
Public Property Lastname As String
Sub New()
End Sub
End Class
Sub New()
End Sub
End Class
用 500.000 个对象填充列表:
oNames.cNames.Clear()
For i As Integer = 1 To 500000
oNames.cNames.Add(New oNames.oName With {.Firstname = "MyFirstName" & i.ToString, .Lastname = "MyLastName" & i.ToString})
Next
写入二进制文件(使用我自己的序列化器class):
WCC.BinSerialization.ToFile(oNames.cNames, "c:\temp\ObjToBin.bin", IO.FileMode.Append)
写入XML文件(使用我自己的序列化器class):
WCC.XMLSerialization.Obj_To_XMLFile(oNames.cNames, "c:\temp\ObjToXML.xml")
写入XML-string(使用我自己的序列化器class):
Dim XMLStr As String
XMLStr = WCC.XMLSerialization.Obj_To_XLMStr(oNames.cNames)
我的序列化器class:
Public Class WCC
Public Class XMLSerialization
Public Shared Function Obj_To_XLMStr(Obj As Object) As String
Using SW As New System.IO.StringWriter
Dim X As New System.Xml.Serialization.XmlSerializer(Obj.GetType)
X.Serialize(SW, Obj)
Return SW.ToString
End Using
End Function
Public Shared Sub XMLStr_To_Obj(XMLString As String, ByRef ListObj As Object)
Using SR As New System.IO.StringReader(XMLString)
Dim X As New System.Xml.Serialization.XmlSerializer(ListObj.GetType)
ListObj = X.Deserialize(SR)
End Using
End Sub
Public Shared Sub Obj_To_XMLFile(Obj As Object, Path As String)
Dim XWS As New System.Xml.XmlWriterSettings
XWS.Indent = True
XWS.IndentChars = vbTab
Using XW As System.Xml.XmlWriter = System.Xml.XmlWriter.Create(Path, XWS)
Dim X As New System.Xml.Serialization.XmlSerializer(Obj.GetType)
X.Serialize(XW, Obj)
End Using
End Sub
End Class
Public Class BinSerialization
Public Shared Sub ToFile(Obj As Object, Path As String, FileMode As IO.FileMode)
Using fs As New System.IO.FileStream(Path, FileMode)
Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
bf.Serialize(fs, Obj)
End Using
End Sub
End Class
End Class