2

我设置了这个空属性:

在此处输入图像描述

但是在为属性分配一个新的ArrayList对象后,该属性在每次应用程序执行中始终为空。

MyBase.Load事件的处理程序中,我调用了这个方法,只是为了测试这个问题:

sub blahblah handles mybase.load
    me.CheckRecentFiles
end sub

Private Sub CheckRecentFiles()

    Try
        ' This throws an object not referenced exception 'cause always is empty.
        MsgBox(My.Settings.RecentFiles.Count)
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try

    ' Just for testing, if the collection is empty then I instance a new ArrayList
    ' and I assign it to the property and I save it and exit from the application.
    ' But even doing this the property is always empty in the next execution.
    If My.Settings.RecentFiles Is Nothing Then

        My.Settings.RecentFiles = New ArrayList
        My.Settings.RecentFiles.Add({"test-Item1", "test-Item2", "Test-Item3"})
        My.Settings.Save()
        Application.Exit()

    End If

End Sub

正如您在上面的代码中看到的那样,我正在为一个新的 ArrayList 分配一个条目,但更改仅在该应用程序执行期间生效,如果我退出应用程序,则该属性再次变为空。

当然,我也检查了这个选项:

在此处输入图像描述

但无论如何这是不必要的,因为我在代码中手动保存设置,所以......

为什么会这样?。

我该如何解决这个问题?

更新:

我进行了调查,似乎这是一个已知问题,即 my.settings 无法保存数组、ArrayLists 和任何通用集合(类型)(但另一方面,StringCollection 可以)

但是在这篇文章的最后一个答案(MemoryStream 答案)中,解释了一种将 ArrayList 的更改永久保存到 my.settings 的简单方法,然后在下一次应用程序运行时读取它。

答案似乎很好,但是我对代码和继续执行的步骤有点迷茫,所以有人可以解释那里解释的步骤,但请用一种人类可读的语言来解释我吗?

我已经验证 ArrayList 仍然在下一个应用程序运行中,是的,但我不确定我在做什么,因为如果 MemoryStream 包含旧的 ArrayList,那么我现在正在做的是分配 My.Settings。 MRU 设置为 Arraylist,其中包含更多内容,Arraylists而不是包含 ? 的原始 ArrayList,String()无论如何在以这种方式保存设置后如何加载数组条目?

这是我从那个答案中尝试过的:

' Create the ArrayList
Dim tmpArrayList = New System.Collections.ArrayList
tmpArrayList.Add({"test-Item1-1", "test-Item1-2", "Test-Item1-3"})
tmpArrayList.Add({"test-Item2-1", "test-Item2-2", "Test-Item2-3"})

' Serialize the arraylist entries:
Dim formatter As Runtime.Serialization.IFormatter =
    New Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim ms1 As New IO.MemoryStream
formatter.Serialize(ms1, tmpArrayList)

' Save the ArrayList
My.Settings.MRU = New ArrayList(ms1.ToArray) ' I think it hould be like that?

' Load the ArrayList contained in My.Settings.MRU (no idea)
4

1 回答 1

2

如果您在 arrayList(或 List 或 Collection)中有数据,并且您正在查看 BinaryFormatter 的解决方法,则没有充分的理由也使用 My.Settings。您可以通过 BinaryFormatter 完成它所做的事情,它只是保存文件并选择一个名称。

Imports System.Runtime.Serialization.Formatters.Binary

Private MRUArrayList = New ArrayList
' file location
 myFile = System.IO.Path.Combine(Environment.GetFolderPath(Environment. _
                    SpecialFolder.ApplicationData),
                                    CompName,
                                    ProgramName,
                                    File)

保存设置:

Dim bf As New BinaryFormatter
Using fs As New FileStream(myFile, FileMode.OpenOrCreate)
    bf.Serialize(fs, MRUArrayList )
End Using

加载设置:

' dont attempt for the first time run
If File.Exists(myFile) = False Then Return False

Dim bf As New BinaryFormatter
Using fs As New FileStream(myFile, FileMode.Open)
    MRUArrayList = CType(bf.Deserialize(fs), ArrayList)
End Using

一旦您不得不求助于 BF 解决方法,用 File Stream 替换 Memory Stream 就可以完全摆脱对 My.Settings 的需要,让您可以将文件存储在任何您想要的地方并且它不会因版本而改变,用户更改 EXE 名称或其他任何内容,除非您更改上面的文件名公式。

对于不仅仅是 MRU ArrayList 的应用程序,您可以使用一个类来将所有设置存储到您想要的位置,就像设置一样。您只需要将 Class 标记为<Serializable>. 只需要一行代码来保存整个类,用一行代码来重构它。有一些限制,但它们并不难克服。

Private myNewSettings As New myNewSettingsClass
...

bf.Serialize(fs, myNewSettings)

myNewSettings = CType(bf.Deserialize(fs), myNewSettingsClass )

在其他情况下,您可以根据需要使用 XML 序列化程序或 ProtoBuf-NET。

您还可以在程序退出时自动保存新设置:转到Project Properties --> Application --> 单击 View Application Events。从左侧菜单中选择“应用程序事件”,从右侧事件菜单中选择 关闭。

Private Sub MyApplication_Shutdown(sender As Object, 
          e As EventArgs) Handles Me.Shutdown

   ' add your code to Save (above) here
End Sub

同样,您可以让它在Startup事件中自动加载它们。

于 2014-07-29T11:42:50.373 回答