1、关于串行化和反串行化
串行化:将对象的状态保存或者永久保存到磁盘中的动作。
反串行化:通过即将存储在磁盘上的信息读回对象的类中来推向对象状态的动作。
默认情况下基本数据类型(byte,char,int,long,double,string)是不能串行化的。所以必须用要串行化的对象的类源文件顶部的【Serializable】属性,来显示指出该对象可以被串行化。
2、串行化和随机文件的区别
随机访问程序的意图:作为一种永久存储对象的基于事务结构。
对象的串行化:常用来临时存储对象的状态。以便以后可以恢复。
可能不想让所有的信息都放在一个串行化类中。如果将一个类中的某个特定成员排除在外,不将它串行化为对象状态的一部分,可以在类中定义如下语句:
[NonSerialized] string cellPhone;
以上语法将手机号标记为从串行化到磁盘的属性中排除。
如果类中包括其他数据类型,比如自定义类,那么那些类必须用[Serializable]属性集编译。如果具备对这些类的源代码访问权限,这可能不是问题。但如果没有源代码的商业产品当中的一个类,可能就无法将该对象标记为可串行化。
一下给出示例程序,具体串行化实现细节在程序中以注释形式标出。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
//注意各种必须添加到文件上方的include
//重要的是要在紧靠类签名的前面添加【Serialization】
//如果没有成功完成这件事情,那么就会比较棘手。
//没有他编译文件的话,则不得不从头开始。
[Serializable]
class clsSerial
{
private string name;
private string email;
private int status;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public string Email
{
get
{
return email;
}
set
{
email = value;
}
}
public int Status
{
get
{
return status;
}
set
{
status = value;
}
}
//将信息串行化到磁盘中。
public int SerializeFriend(clsSerial myFriend)
{
try
{
BinaryFormatter format = new BinaryFormatter();
FileStream myStream = new FileStream("Test.txt", FileMode.Create);
//打开名为test的测试文件,如果将FileMode的creat改为
//Append,那么可以向文件中附加多个对象的状态。
format.Serialize(myStream, myFriend);
//然后利用BinaryFormatter类的Serialize方法将myFriend
//的状态存储到磁盘上。
myStream.Close();
}
catch(Exception ex)
{
string buff = ex.Message;
return 0;
}
return 1;
}
//从磁盘文件中反串行化数据。
public clsSerial DeserializeFriend()
{
clsSerial temp = new clsSerial();
try
{
BinaryFormatter format = new BinaryFormatter();
FileStream myStream = new FileStream("Test.txt", FileMode.Open);
temp = (clsSerial)format.Deserialize(myStream);
//从磁盘文件中读取数据,并且格式化为clsSerial对象。
//显式类型强制转化是必须的。Deserialize()返回一个纯对象类型
myStream.Close();
}
catch (Exception ex)
{
string buff = ex.Message;
return null;
}
return temp;
}
}
frmMain函数
using System;
using System.Windows.Forms;
public class frmMain : Form
{
clsSerial myFriend = new clsSerial();
private Label label1;
private Label label2;
private Label label3;
private TextBox txtName;
private TextBox txtEmail;
private TextBox txtStatus;
private Button btnSerial;
private Button btnDisplay;
private Button btnClose;
private ListBox lstOutput;
#region Windows code
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.txtName = new System.Windows.Forms.TextBox();
this.txtEmail = new System.Windows.Forms.TextBox();
this.txtStatus = new System.Windows.Forms.TextBox();
this.btnSerial = new System.Windows.Forms.Button();
this.btnDisplay = new System.Windows.Forms.Button();
this.btnClose = new System.Windows.Forms.Button();
this.lstOutput = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// label1
//
this.label1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.label1.Location = new System.Drawing.Point(38, 34);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(78, 23);
this.label1.TabIndex = 0;
this.label1.Text = "Name";
this.label1.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// label2
//
this.label2.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.label2.Location = new System.Drawing.Point(38, 76);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(78, 23);
this.label2.TabIndex = 1;
this.label2.Text = "Email";
this.label2.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// label3
//
this.label3.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.label3.Location = new System.Drawing.Point(38, 114);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(78, 23);
this.label3.TabIndex = 2;
this.label3.Text = "Status";
this.label3.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// txtName
//
this.txtName.Location = new System.Drawing.Point(158, 36);
this.txtName.Name = "txtName";
this.txtName.Size = new System.Drawing.Size(244, 21);
this.txtName.TabIndex = 3;
//
// txtEmail
//
this.txtEmail.Location = new System.Drawing.Point(158, 74);
this.txtEmail.Name = "txtEmail";
this.txtEmail.Size = new System.Drawing.Size(244, 21);
this.txtEmail.TabIndex = 4;
//
// txtStatus
//
this.txtStatus.Location = new System.Drawing.Point(158, 116);
this.txtStatus.Name = "txtStatus";
this.txtStatus.Size = new System.Drawing.Size(100, 21);
this.txtStatus.TabIndex = 5;
//
// btnSerial
//
this.btnSerial.Location = new System.Drawing.Point(38, 170);
this.btnSerial.Name = "btnSerial";
this.btnSerial.Size = new System.Drawing.Size(75, 23);
this.btnSerial.TabIndex = 6;
this.btnSerial.Text = "Serialize";
this.btnSerial.UseVisualStyleBackColor = true;
this.btnSerial.Click += new System.EventHandler(this.btnSerial_Click);
//
// btnDisplay
//
this.btnDisplay.Location = new System.Drawing.Point(196, 169);
this.btnDisplay.Name = "btnDisplay";
this.btnDisplay.Size = new System.Drawing.Size(75, 23);
this.btnDisplay.TabIndex = 7;
this.btnDisplay.Text = "Display";
this.btnDisplay.UseVisualStyleBackColor = true;
this.btnDisplay.Click += new System.EventHandler(this.btnDisplay_Click);
//
// btnClose
//
this.btnClose.Location = new System.Drawing.Point(347, 169);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(75, 23);
this.btnClose.TabIndex = 8;
this.btnClose.Text = "Close";
this.btnClose.UseVisualStyleBackColor = true;
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// lstOutput
//
this.lstOutput.FormattingEnabled = true;
this.lstOutput.ItemHeight = 12;
this.lstOutput.Location = new System.Drawing.Point(38, 222);
this.lstOutput.Name = "lstOutput";
this.lstOutput.Size = new System.Drawing.Size(384, 136);
this.lstOutput.TabIndex = 9;
//
// frmMain
//
this.ClientSize = new System.Drawing.Size(466, 395);
this.Controls.Add(this.lstOutput);
this.Controls.Add(this.btnClose);
this.Controls.Add(this.btnDisplay);
this.Controls.Add(this.btnSerial);
this.Controls.Add(this.txtStatus);
this.Controls.Add(this.txtEmail);
this.Controls.Add(this.txtName);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Name = "frmMain";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
//#region是C# 预处理器指令。
//#region 使您可以在使用 Visual Studio
//代码编辑器的大纲显示功能时指定可展开或折叠的代码块。
public frmMain()
{
InitializeComponent();
}
public static void Main()
{
frmMain main = new frmMain();
Application.Run(main);
}
//简单地将三个属性复制到myFriend对象的与他们
//关联的成员中。
private void MoveTextToClass(clsSerial obj)
{
bool flag;
int val;
obj.Name = txtName.Text;
obj.Email = txtEmail.Text;
flag = int.TryParse(txtStatus.Text,out val);
if (flag == false)
{
MessageBox.Show("Must Be 1 or 0","Input Error");
txtStatus.Focus();
return;
}
obj.Status = val;
}
private void btnSerial_Click(object sender, EventArgs e)
{
int flag;
MoveTextToClass(myFriend);
flag = myFriend.SerializeFriend(myFriend);
if (flag == 1)
{
MessageBox.Show("Data Serialized successfully", "Data Write");
}
else
{
MessageBox.Show("Data Serialized failure","Data Error");
}
}
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
private void btnDisplay_Click(object sender, EventArgs e)
{
clsSerial newFriend = new clsSerial();
newFriend = newFriend.DeserializeFriend();
lstOutput.Items.Add(newFriend.Name);
lstOutput.Items.Add(newFriend.Email);
lstOutput.Items.Add(newFriend.Status.ToString());
}
}
3、MDI、菜单和文件对话框
MDI:Multiple Document Interface。多文档界面。
创建项目:使用Design窗口中所示的frmMain窗体,将窗体的IsMdiContainer属性设置为true。设置以后,窗体风格会改变。窗体客户端区变成了深灰色色调。滚动到窗体属性列表的底部,将WindowsState属性设置为Maximized。(frmMain的程序框将会占满整个显示屏。)
设计窗口:来到ToolBox窗口中,打开Menu&ToolBars部分。并且双击MenuStrip对象。可以添加一个菜单栏。即可以设计相关菜单选项。
MenuStrip对象出现在屏幕的底部System Tray区域中。
C# [STAThread]
每个Thread都有一个关于ApartmentState的属性,可以把它设置为:STA或者MTA,或者UNKNOWN。
当你想指定工程的启动窗口的时候,你需要在该窗口类中申明一个Main()方法,并为这个方法设置[STAThread]属性。
[STAThread]是Single Thread Apartment单线程套间的意思,是一种线程模型,用在程序的入口方法上
(在C#和VB.NET里是Main()方法),来指定当前线程的ApartmentState 是STA。用在其他方法上不产生影响。
在aspx页面上可以使用AspCompat = “true” 来达到同样的效果。这个属性只在 Com Interop 有用,
如果全部是 managed code 则无用。简单的说法:[STAThread]指示应用程序的默认线程模型是单线程单元 (STA)。
启动线程模型可设置为单线程单元或多线程单元。如果未对其进行设置,则该线程不被初始化。也就是说如果你用的.NET Framework,
并且没有使用COM Interop,一般不需要这个Attribute。其它的还有MTA(多线程套间)、Free Thread(自由线程)。
单线程套间,简单来说所有对于单线程套间中对象的访问都是通过消息来传递的,所以同一时间只有一个线程能够访问单线程套间中的对象。
引自作者:blogsweb
实例代码:
using System;
using System.Windows.Forms;
public class frmMain : Form
{
string selectFile;
private MenuStrip menuStrip2;
private ToolStripMenuItem mnuFile;
private ToolStripMenuItem mmuOpen;
private ToolStripMenuItem mnuEdit;
private ToolStripSeparator toolStripMenuItem2;
private OpenFileDialog openFileDialog1;
private ToolStripMenuItem mnuExit;
#region Windows code
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain));
this.menuStrip2 = new System.Windows.Forms.MenuStrip();
this.mnuFile = new System.Windows.Forms.ToolStripMenuItem();
this.mmuOpen = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEdit = new System.Windows.Forms.ToolStripMenuItem();
this.mnuExit = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.menuStrip2.SuspendLayout();
this.SuspendLayout();
//
// menuStrip2
//
this.menuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuFile});
this.menuStrip2.Location = new System.Drawing.Point(0, 0);
this.menuStrip2.Name = "menuStrip2";
this.menuStrip2.Size = new System.Drawing.Size(569, 25);
this.menuStrip2.TabIndex = 2;
this.menuStrip2.Text = "menuStrip2";
//
// mnuFile
//
this.mnuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mmuOpen,
this.mnuEdit,
this.toolStripMenuItem2,
this.mnuExit});
this.mnuFile.Name = "mnuFile";
this.mnuFile.Size = new System.Drawing.Size(39, 21);
this.mnuFile.Text = "&File";
//
// mmuOpen
//
this.mmuOpen.Name = "mmuOpen";
this.mmuOpen.Size = new System.Drawing.Size(152, 22);
this.mmuOpen.Text = "&Open";
this.mmuOpen.Click += new System.EventHandler(this.mmuOpen_Click);
//
// mnuEdit
//
this.mnuEdit.Name = "mnuEdit";
this.mnuEdit.Size = new System.Drawing.Size(191, 22);
this.mnuEdit.Text = "&Edit";
//
// mnuExit
//
this.mnuExit.Image = ((System.Drawing.Image)(resources.GetObject("mnuExit.Image")));
this.mnuExit.Name = "mnuExit";
this.mnuExit.Size = new System.Drawing.Size(152, 22);
this.mnuExit.Text = "E&xit";
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(149, 6);
this.toolStripMenuItem2.Click += new System.EventHandler(this.toolStripMenuItem2_Click);
//
// openFileDialog1
//
this.openFileDialog1.FileName = "openFileDialog1";
this.openFileDialog1.FileOk += new System.ComponentModel.CancelEventHandler(this.openFileDialog1_FileOk);
//
// frmMain
//
this.ClientSize = new System.Drawing.Size(569, 445);
this.Controls.Add(this.menuStrip2);
this.IsMdiContainer = true;
this.Name = "frmMain";
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
this.menuStrip2.ResumeLayout(false);
this.menuStrip2.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
//#region是C# 预处理器指令。
//#region 使您可以在使用 Visual Studio
//代码编辑器的大纲显示功能时指定可展开或折叠的代码块。
public frmMain()
{
InitializeComponent();
}
//当用调试器运行该程序的时候,西药下行语句。
//告诉编译器使用单线程套间来生成代码。
//C#可以让多个现成或进程同步运行,不必详细了解。
//使用这个语句确保用单个线程与FileOpenDialog对象通信。
[STAThread]
public static void Main()
{
frmMain main = new frmMain();
Application.Run(main);
}
private void toolStripMenuItem2_Click(object sender, EventArgs e)
{
}
private void openFileDialog1_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
{
}
private void mmuOpen_Click(object sender, EventArgs e)
{
OpenFileDialog fileOpen = new OpenFileDialog();
//创建了OpenFileDialog对象的一个实例。
fileOpen.Title = "Select file to open ";
//Title属性简单的设置了出现在文件对话框标题
//栏中的文本。
fileOpen.Filter = "(*.bin)|*.bin|(*.txt)|*.txt|All files(*.*)|*.*";
//Filter属性设置在运行对话框时希望看到的文件类型。
if (fileOpen.ShowDialog() == DialogResult.OK)
{
//如果在程序菜单中单击OK
//selectFile变量将会存放该文件的名称
//以及它的完整路径名。
selectFile = fileOpen.FileName;
}
}
}
4、调用另一个窗体
可以向上一个项目中添加另一个窗体。在代码中删除相关的Main()代码。(一个程序中只能够有一个main函数)关于调用窗体的实例:
private void MNUEdit_Click(object sender,EventArgs e)
{
frmEditFriend frm=new frmEditFriend();
frm.ShowDialog();
//showDialog方法将该对象显示到屏幕上。
}
注意子窗口文件的创建必须要在命名空间内部。在主窗口的源代码注意using一下命名空间。
Form2 form=new Form2();
如果是打开模式对话框就
form.ShowDialog();
如果不是就
form.Show();
例子如上。