チュートリアル: オブジェクトの永続化 (C# および Visual Basic)
デザイン時にオブジェクトのプロパティを既定値に設定できますが、実行時に入力した値はオブジェクトが破棄されるとすべて失われます。シリアル化を使用してインスタンス間でオブジェクトのデータを永続化することで、次にそのオブジェクトのインスタンスを生成するときに値を格納および取得できます。
[!メモ]
Visual Basic では、名前や数字などの単純なデータを格納する場合は、My.Settings オブジェクトを使用できます。詳細については、「My.Settings オブジェクト」を参照してください。
このチュートリアルでは、簡単な Loan オブジェクトを作成し、そのデータをファイルに永続化します。そして、オブジェクトの再作成時にファイルからデータを取得します。最後に、コードを変更して SOAP 形式でオブジェクトを永続化します。
セキュリティに関するメモ |
---|
次のコード例では、ファイルが存在しない場合は新規にファイルを作成します。アプリケーションがファイルを作成する必要がある場合は、フォルダーの Create のアクセス許可が必要になります。アクセス許可は、アクセス制御リストを使用して設定します。ファイルが既に存在する場合、アプリケーションに必要なのは Write のアクセス許可だけです。可能な場合は、配置時にファイルを作成し、フォルダーにはファイルの作成アクセスを許可せず、1 つのファイルだけに Read のアクセス許可を付与する方が安全です。また、ルート フォルダーや 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」と入力し、[OK] をクリックしてダイアログ ボックスを閉じます。
ソリューション エクスプローラーでプロジェクトを選択します。
[プロジェクト] メニューの [スタートアップ プロジェクトに設定] をクリックします。
[プロジェクト] メニューの [参照の追加] をクリックします。
[参照の追加] ダイアログ ボックスで、[プロジェクト] タブをクリックし、[LoanClass] プロジェクトをクリックします。
[OK] をクリックし、ダイアログ ボックスを閉じます。
デザイナーで、フォームに 4 つの 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(); }
この時点で、アプリケーションを再度ビルドして実行できます。最初に既定値がテキスト ボックスに表示されます。値を変更して、4 番目のテキスト ボックスに名前を入力します。いったんアプリケーションを閉じて、再び実行します。これで、新しい値がテキスト ボックスに表示されます。
SOAP 形式を使用したオブジェクトの永続化
これまで紹介した例では、バイナリ形式を使用してテキスト ファイルにオブジェクトを永続化する方法を説明しました。バイナリ形式は、ほとんどの Windows アプリケーションで問題なく使用できます。Web アプリケーションまたは Web サービスの場合は、SOAP 形式を使用して XML ファイルにオブジェクトを永続化した方がオブジェクトの共有が簡単になります。
オブジェクトを SOAP 形式で永続化するには、まず SoapFormatter クラスを参照する必要があります。SoapFormatter クラスは、自らの名前空間 System.Runtime.Serialization.Formatters.Soap にあります。
SOAP 形式を使用してオブジェクトを永続化するには
ソリューション エクスプローラーでプロジェクトを選択します。
[プロジェクト] メニューの [参照の追加] をクリックします。
[参照の追加] ダイアログ ボックスで、[.NET] タブをクリックし、System.Runtime.Serialization.Formatters.Soap コンポーネントをクリックします。
[OK] をクリックし、ダイアログ ボックスを閉じます。
コード エディターで、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 Application プロジェクトの [Bin] ノード内にあります。
[!メモ]
既に [すべてのファイルを表示] モードになっている場合、ファイルを表示するには、[表示] メニューの [最新の情報に更新] をクリックして最新の内容に更新する必要があります。
LoanClass の 3 つのメンバーは、XML 形式で表示されます。XML ファイルで InterestRate の値を変更して保存してから、アプリケーションを再度実行してください。新しい利率が、2 番目のテキスト ボックスに表示されます。