本分步指南介绍如何使用 C# 来作为程序集的一部分嵌入资源,然后在运行时访问资源。
概述
.NET Framework 可以封装文件,为已编译的程序集的一部分。这些文件称为嵌入的资源。这些资源是完全独立的程序集相关联的.resources 和.resx 文件。您可以在运行时通过的System.Reflection命名空间的程序集类访问这些资源。
嵌入的清单资源的主要优点是因为这些文件是已编译的程序集的一部分,用户不能意外删除或误放到您的应用程序,这在某些情况下可能会阻止程序的执行至关重要的文件。这种方法的一个限制是您无法保存任何更改到此文件的程序集无需重新编译该程序。正因为如此,只包含作为嵌入资源的应用程序的生存期内将不会更改的文件。
分步演示
若要将嵌入的资源添加到您的项目中,必须首先为您的项目的一部分添加这些文件。将文件添加到项目后,您可以访问和显示通过System.Reflection命名空间中的资源。
添加嵌入的资源
要添加文本文件和图像文件作为资源嵌入到您的项目,请按照下列步骤操作:
为此演示创建一个新的 Windows 应用程序项目。此窗体用于显示从执行的程序集在运行时访问的资源。
用鼠标右键单击项目名称,单击添加,然后单击添加新项
在新建项目对话框中,从菜单上,选择文本文件,并命名为 MyTextFile.txt 的文件。在集成的开发环境 (IDE) 中打开了该文件,添加一些文本,,然后关闭该文件。
重复步骤 1 和 2,将位图图像添加到项目中,但而不是作为新的项目类型中选择文本文件,选择位图文件,然后将文件名更改为MyImage.bmp。当在 IDE 中打开新图像时,图像上, 绘制的内容,然后关闭该文件。
用鼠标右键单击文件文本或位图,然后选择属性
在属性对话框中,找到生成操作属性。默认情况下,此属性设置为内容。请单击该属性并将生成操作属性更改为嵌入的资源
对另一个文件重复步骤 4 和 5。
下一次生成项目时,编译器将这些文件添加到您的程序集。它包含在项目中时,编译器会将项目的根命名空间添加到的资源的名称。例如,如果您的项目的根命名空间是 MyNamespace,资源被命名为 MyNamespace.MyTextFile.txt 和 MyNamespace.MyImage.bmp。
请注意: 资源文件的名称是区分大小写。在访问资源时,您必须使用的确切拼写和大小写的文件名。如果您不使用的确切拼写和大小写的文件名,该方法调用来访问ManifestResourceStream返回执行任何操作,并且系统不会引发异常。
注意: 如果您想要验证这些资源名称,您可以使用 Microsoft 中间语言拆装器 (ILDASM) 查看清单数据,其中列出了所包括的资源。
访问资源
若要访问已在您的程序集的清单中嵌入的资源,导System.IO和System.Reflection命名空间中,按如下所述:
using System.IO; using System.Reflection;
System.IO命名空间提供了流的定义和System.Reflection命名空间中定义的程序集提供的类的方法,以访问程序集中嵌入的资源。
声明在以下常规声明区域中的时,在加载窗体时读取从程序集中的资源:
Assembly _assembly; Stream _imageStream; StreamReader _textStreamReader;
注意: 要访问在代码编辑器中的窗体的Load事件,请双击该窗体在设计编辑器。
若要读取从正在执行的当前代码的程序集的资源,您必须获取该程序集的一个实例。若要执行此操作,使用该程序集,GetExecutingAssembly方法,如下所示:
_assembly = Assembly.GetExecutingAssembly();
从资源到流中读取信息,对GetManifestResourceStream的方法调用执行。传递给此方法的参数是要访问的资源的名称。在执行该窗体的Load事件,然后读取两个资源到其相应的流。
_imageStream = _assembly.GetManifestResourceStream("MyNameSpace.MyImage.bmp"); _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("MyNameSpace.MyTextFile.txt"));
在窗体的Load事件中的代码如下所示:
try { _assembly = Assembly.GetExecutingAssembly(); _imageStream = _assembly.GetManifestResourceStream("MyNamespace.MyImage.bmp"); _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("MyNamespace.MyTextFile.txt")); } catch { MessageBox.Show("Error accessing resources!"); }
Try-catch语句中,称为在.NET 中,结构化的错误处理用于捕捉的程序集类的实例访问资源时可能发生的任何错误。
显示资源
此示例使用两个按钮以显示嵌入的资源。单击第一个按钮时,基于从程序集中读取资源的位图图像创建,并显示在窗体的图片框控件中。第二个按钮的文本资源从读取,并在文本框中显示的文本。
若要显示嵌入的资源,请执行以下步骤:
将图片框控件添加到窗体中。
将一个新的按钮控件添加到窗体中,然后再将它的Text属性更改为显示图像
双击该按钮以打开其Click事件,在代码查看器中,然后将下面的代码粘贴在这种情况:
try { pictureBox1.Image = new Bitmap(_imageStream); } catch { MessageBox.Show("Error creating image!"); }
该代码生成基于窗体的Load事件中读取资源流的位图中的一个新实例。
向表单中添加文本框控件。
将另一个按钮控件添加到窗体上,然后再将它的Text属性更改为获取文本
双击设计编辑器中打开Click_Event的按钮,该按钮,然后将下面的代码粘贴在该事件中:
try { if(_textStreamReader.Peek() != -1) { textBox1.Text = _textStreamReader.ReadLine(); } } catch { MessageBox.Show("Error writing text!"); }
此代码确定要读取的字符是否仍然存在在流中。如果找到的字符,文本框中将读取行。
按 F5 键运行该应用程序。
完整的代码
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.IO; using System.Reflection; namespace MyNamespace { /// <summary> /// Summary description for Form1. /// </summary> public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.PictureBox pictureBox1; private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.Button button1; private System.Windows.Forms.Button button2; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public Form1() { // // Required for Windows Form Designer support. // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call. // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.textBox1 = new System.Windows.Forms.TextBox(); this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // pictureBox1 // this.pictureBox1.Location = new System.Drawing.Point(4, 8); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Size = new System.Drawing.Size(284, 192); this.pictureBox1.TabIndex = 0; this.pictureBox1.TabStop = false; // // textBox1 // this.textBox1.Location = new System.Drawing.Point(92, 236); this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(192, 20); this.textBox1.TabIndex = 1; this.textBox1.Text = "textBox1"; // // button1 // this.button1.Location = new System.Drawing.Point(8, 208); this.button1.Name = "button1"; this.button1.TabIndex = 2; this.button1.Text = "Show Image"; this.button1.Click += new System.EventHandler(this.button1_Click); // // button2 // this.button2.Location = new System.Drawing.Point(8, 236); this.button2.Name = "button2"; this.button2.TabIndex = 3; this.button2.Text = "Get Text"; this.button2.Click += new System.EventHandler(this.button2_Click); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(292, 266); this.Controls.AddRange(new System.Windows.Forms.Control[]{ this.button2, this.button1, this.textBox1, this.pictureBox1}); this.Name = "Form1"; this.Text = "Form1"; this.Load += new System.EventHandler(this.Form1_Load); this.ResumeLayout(false); } #endregion Assembly _assembly; Stream _imageStream; StreamReader _textStreamReader; /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new Form1()); } private void Form1_Load(object sender, System.EventArgs e) { try { _assembly = Assembly.GetExecutingAssembly(); _imageStream = _assembly.GetManifestResourceStream("MyNamespace.MyImage.bmp"); _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("MyNamespace.MyTextFile.txt")); } catch { MessageBox.Show("Error accessing resources!"); } } private void button1_Click(object sender, System.EventArgs e) { try { pictureBox1.Image = new Bitmap(_imageStream); } catch { MessageBox.Show("Error creating image!"); } } private void button2_Click(object sender, System.EventArgs e) { try { if(_textStreamReader.Peek() != -1) { textBox1.Text = _textStreamReader.ReadLine(); } } catch { MessageBox.Show("Error writing text!"); } } } }
注意在 Visual Studio 2005年中或在 Visual Studio 2008 中,则应更改代码。创建一个 Windows 窗体项目时,Visual C# 一个窗体向项目中添加默认情况下。此窗体名为 Form1。表示窗体的两个文件称为 Form1.cs 和 Form1.designer.cs。Form1.cs 中编写您的代码。Designer.cs 文件是 Windows 窗体设计器编写的代码实现的所有操作,您通过添加控件来执行。有关 Windows 窗体设计器在 Visual C# 2005年或 Visual Studio 2008 中的详细信息,请访问下面的 Microsoft Web 站点:
http://msdn2.microsoft.com/en-us/library/ms173077.aspx
故障排除
由于资源名称是区分大小写,请验证您正在使用相应的拼写和大小写的资源的访问。您可以使用 ILDASM 读取清单的数据,来验证资源的确切拼写。
以上就是如何嵌入和使用C#来访问资源的代码详解的详细内容,更多请关注php中文网其它相关文章!