演练:保持对象(C# 和 Visual Basic)
虽然您可以在设计时将对象的属性设置为默认值,但是,如果该对象被损环,则在运行时输入的所有值均会丢失。 可以使用序列化在实例之间保持对象数据,从而能够存储值并且在下次实例化对象时检索这些值。
提示
在 Visual Basic 中,若要存储简单数据(例如名称或数字),可以使用 My.Settings 对象。 有关更多信息,请参见 My.Settings 对象 (Visual Basic)。
在本演练中,将创建一个简单的 Loan 对象,并将该对象的数据保存到文件中。 然后,当您重新创建对象时将从该文件检索数据。 最后,将修改代码以使用 SOAP 格式保持对象。
安全说明 |
---|
本示例创建新的文件(如果该文件尚未存在)。 如果应用程序必须创建文件,则该应用程序必须具有该文件夹的 Create 权限。 权限可使用访问控制列表进行设置。 如果该文件已经存在,则应用程序仅需要 Write 权限(它比 Create 权限弱)。 应尽可能在部署过程中创建文件并仅向单个文件授予 Read 权限(而不是向文件夹授予 Create 权限),这样做更安全。 而且,更为安全的方法是将数据写入用户文件夹,而不是写入根文件夹或“Program Files”文件夹。 |
安全说明 |
---|
本示例将数据存储到二进制或 SOAP 格式的文件中。 不应将这些格式用于敏感数据,如密码或信用卡信息。 |
提示
显示的对话框和菜单命令可能会与“帮助”中的描述不同,具体取决于您现用的设置或版本。 若要更改设置,请单击“工具”菜单上的“导入和导出设置”。 有关更多信息,请参见 Visual Studio 设置。
创建 Loan 对象
第一步是创建 Loan 类和使用该类的测试应用程序。
创建 Loan 类
新建“类库”项目,并将其命名为“LoanClass”。 有关更多信息,请参见如何:创建解决方案和项目。
在**“解决方案资源管理器”中右击 Class1 文件,并单击“重命名”**。 将该文件重命名为 Loan,并按 Enter。 重命名该文件后,会相应地将类重命名为 Loan。
将以下公共成员添加到该类中:
Public Class Loan Implements System.ComponentModel.INotifyPropertyChanged Public Property LoanAmount As Double Public Property InterestRate As Double Public Property Term As Integer Private p_Customer As String Public Property Customer As String Get Return p_Customer End Get Set(ByVal value As String) p_Customer = value RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("Customer")) End Set End Property Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler _ Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged Public Sub New(ByVal loanAmount As Double, ByVal interestRate As Double, ByVal term As Integer, ByVal customer As String) Me.LoanAmount = loanAmount Me.InterestRate = interestRate Me.Term = term p_Customer = customer End Sub End Class
public class Loan : System.ComponentModel.INotifyPropertyChanged { public double LoanAmount {get; set;} public double InterestRate {get; set;} public int Term {get; set;} private string p_Customer; public string Customer { get { return p_Customer; } set { p_Customer = value; PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Customer")); } } public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; public Loan(double loanAmount, double interestRate, int term, string customer) { this.LoanAmount = loanAmount; this.InterestRate = interestRate; this.Term = term; p_Customer = customer; } }
您还必须创建一个使用 Loan 类的简单应用程序。
创建测试应用程序
若要向解决方案中添加 Windows 窗体应用程序项目,请在**“文件”菜单上指向“添加”,然后单击“新建项目”**。
在**“添加新项目”对话框中,输入 LoanApp 作为项目的名称,然后单击“确定”**以关闭该对话框。
在**“解决方案资源管理器”**中选择 LoanApp 项目。
在**“项目”菜单上,单击“设为启动项目”**。
在**“项目”菜单上,单击“添加引用”**。
在**“添加引用”对话框中,选择“项目”**选项卡,然后选择“LoanClass”项目。
单击**“确定”**关闭对话框。
在设计器中,将四个 TextBox 控件添加到窗体。
在代码编辑器中,添加以下代码:
Private WithEvents TestLoan As New LoanClass.Loan(10000.0, 0.075, 36, "Neil Black") Private Sub Form1_Load() Handles MyBase.Load TextBox1.Text = TestLoan.LoanAmount.ToString TextBox2.Text = TestLoan.InterestRate.ToString TextBox3.Text = TestLoan.Term.ToString TextBox4.Text = TestLoan.Customer End Sub
private LoanClass.Loan TestLoan = new LoanClass.Loan(10000.0, 0.075, 36, "Neil Black"); private void Form1_Load(object sender, EventArgs e) { textBox1.Text = TestLoan.LoanAmount.ToString(); textBox2.Text = TestLoan.InterestRate.ToString(); textBox3.Text = TestLoan.Term.ToString(); textBox4.Text = TestLoan.Customer; }
使用以下代码将 PropertyChanged 事件的事件处理程序添加到窗体:
Public Sub CustomerPropertyChanged( ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs ) Handles TestLoan.PropertyChanged MsgBox(e.PropertyName & " has been changed.") End Sub
private void CustomerPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { MessageBox.Show(e.PropertyName + " has been changed."); }
此时,您就可以生成并运行应用程序了。 请注意,Loan 类的默认值会显示在文本框中。 尝试将利率值从 7.5 更改为 7.1,然后关闭应用程序并再次运行它,利率值会恢复为默认值 7.5。
在现实生活中,利率会定期改变,但不一定是每次运行该应用程序时都改变。 最好在应用程序实例间保持最新的利率,而不是让用户在每次运行应用程序时都更新利率。 在下一步中,将通过向 Loan 类添加序列化来实现这一点。
使用序列化保持对象
为了保持 Loan 类的值,必须先使用 Serializable 特性标记该类。
将类标记为可序列化
更改 Loan 类的类声明,如下所示:
<Serializable()> Public Class Loan
[Serializable()] public class Loan : System.ComponentModel.INotifyPropertyChanged {
Serializable 特性通知编译器可将类中的所有内容保存到文件中。 由于 PropertyChanged 事件由 Windows 窗体对象处理,因此无法对其序列化。 NonSerialized 特性可用于标记不应保留的类成员。
阻止对成员进行序列化
更改 PropertyChanged 事件的声明,如下所示:
<NonSerialized()> Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler _ Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
[field: NonSerialized()] public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
下一步是向 LoanApp 应用程序添加序列化代码。 为了对类进行序列化并将类写入文件,将使用 System.IO 和 System.Xml.Serialization 命名空间。 若要避免键入完全限定名称,您可以添加对必要的类库的引用。
添加对命名空间的引用
将以下语句添加到 Form1 类的顶部:
Imports System.IO Imports System.Runtime.Serialization.Formatters.Binary
using System.IO; using System.Runtime.Serialization.Formatters.Binary;
在这种情况下,您将使用二进制格式化程序以二进制格式保存对象。 在本演练的后半部分,您将修改代码,以 SOAP 格式保存对象。
下一步是添加执行以下任务的代码:在创建对象时从文件反序列化对象。
反序列化对象
将常数添加到序列化数据的文件名的类。
Const FileName As String = "..\..\SavedLoan.bin"
const string FileName = @"..\..\SavedLoan.bin";
修改 Form1_Load 事件过程中的代码,如下所示:
Private WithEvents TestLoan As New LoanClass.Loan(10000.0, 0.075, 36, "Neil Black") Private Sub Form1_Load() Handles MyBase.Load If File.Exists(FileName) Then Dim TestFileStream As Stream = File.OpenRead(FileName) Dim deserializer As New BinaryFormatter TestLoan = CType(deserializer.Deserialize(TestFileStream), LoanClass.Loan) TestFileStream.Close() End If AddHandler TestLoan.PropertyChanged, AddressOf Me.CustomerPropertyChanged TextBox1.Text = TestLoan.LoanAmount.ToString TextBox2.Text = TestLoan.InterestRate.ToString TextBox3.Text = TestLoan.Term.ToString TextBox4.Text = TestLoan.Customer End Sub
private LoanClass.Loan TestLoan = new LoanClass.Loan(10000.0, 0.075, 36, "Neil Black"); private void Form1_Load(object sender, EventArgs e) { if (File.Exists(FileName)) { Stream TestFileStream = File.OpenRead(FileName); BinaryFormatter deserializer = new BinaryFormatter(); TestLoan = (LoanClass.Loan)deserializer.Deserialize(TestFileStream); TestFileStream.Close(); } TestLoan.PropertyChanged += this.CustomerPropertyChanged; textBox1.Text = TestLoan.LoanAmount.ToString(); textBox2.Text = TestLoan.InterestRate.ToString(); textBox3.Text = TestLoan.Term.ToString(); textBox4.Text = TestLoan.Customer; }
请注意,首先必须检查该文件是否存在。 如果它存在,请创建 Stream 类以读取该二进制文件,并创建 BinaryFormatter 类以转换该文件。 您还需要从流类型转换为 Loan 对象类型。
接下来,必须添加代码,将在文本框中输入的数据保存到 Loan 类,然后必须将该类序列化到文件中。
保存数据并对类进行序列化
将下面的代码添加到 Form1_FormClosing 事件过程中:
Private Sub Form1_FormClosing() Handles MyBase.FormClosing TestLoan.LoanAmount = CDbl(TextBox1.Text) TestLoan.InterestRate = CDbl(TextBox2.Text) TestLoan.Term = CInt(TextBox3.Text) TestLoan.Customer = TextBox4.Text Dim TestFileStream As Stream = File.Create(FileName) Dim serializer As New BinaryFormatter serializer.Serialize(TestFileStream, TestLoan) TestFileStream.Close() End Sub
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { TestLoan.LoanAmount = Convert.ToDouble(textBox1.Text); TestLoan.InterestRate = Convert.ToDouble(textBox2.Text); TestLoan.Term = Convert.ToInt32(textBox3.Text); TestLoan.Customer = textBox4.Text; Stream TestFileStream = File.Create(FileName); BinaryFormatter serializer = new BinaryFormatter(); serializer.Serialize(TestFileStream, TestLoan); TestFileStream.Close(); }
此时,您就可以再次生成并运行该应用程序了。 最初,默认值会显示在文本框中。 尝试更改这些值并在第四个文本框中输入名称。 关闭该应用程序,然后重新运行它。 请注意,新值现在将出现在文本框中。
使用 SOAP 格式保持对象
至此,本示例已经演示了如何使用二进制格式将对象保存到文本文件中。 二进制格式对于大多数 Windows 应用程序均适用。 但对于 Web 应用程序或 Web 服务,您可能希望使用 SOAP 格式将对象保存到 XML 文件中,以使对象易于共享。
为了以 SOAP 格式保持对象,您必须先引用 SoapFormatter 类。 SoapFormatter 类驻留在自己的命名空间 System.Runtime.Serialization.Formatters.Soap 中。
使用 SOAP 格式保持对象
在**“解决方案资源管理器”**中选择 LoanApp 项目。
在**“项目”菜单上,单击“添加引用”**。
在**“添加引用”对话框中,单击“.NET”**选项卡,然后选择 System.Runtime.Serialization.Formatters.Soap 组件。
单击**“确定”**关闭对话框。
在**“代码编辑器”**中,将以下语句添加到 Form1 模块的顶部:
Imports System.Runtime.Serialization.Formatters.Soap
using System.Runtime.Serialization.Formatters.Soap;
将文件名从 SavedLoan.bin 更改为 SavedLoan.xml。
在 Form1_Load 事件过程中,将 deserializer 变量的声明更改为以下形式:
Dim deserializer As New SoapFormatter
SoapFormatter deserializer = new SoapFormatter();
在 Form1_FormClosing 事件过程中,将 serializer 变量的声明更改为以下形式:
Dim serializer As New SoapFormatter
SoapFormatter serializer = new SoapFormatter();
此时,您可以生成并测试该应用程序。 第一次运行该应用程序时,会创建 SavedLoan.xml 文件。 若要查看该文件,请在**“解决方案资源管理器”中选择“显示所有文件”**选项;它位于 Windows 应用程序项目的 Bin 节点中。
提示
如果已经处于“显示所有文件”模式下,则必须单击“视图”菜单中的“刷新”来刷新视图以查看此文件。
请注意,LoanClass 的三个成员会以 XML 格式显示。 更改 XML 文件中的 InterestRate 值,然后保存它,并再次运行该应用程序。 新利率将显示在第二个文本框中。