C# Resources资源详解
1.ResourceBasics
(1)ManifestResources(资源清单)
资源在编译期间添加到程序集。如果要将资源嵌入到程序集,则必须将文件添加到项目中,文件会自动拷贝到项目文件夹的Resources文件夹中。如果要嵌入到程序集,还需选中文件,修改其属性“生成操作”(BuildAction)为“嵌入的资源”,默认为“内容”。
一旦设置为嵌入的资源,则它就会成为资源清单中程序集的一部分。每一程序集,无论是静态的还是动态的,均包含描述该程序集中各元素彼此如何关联的数据集合。程序集清单就包含这些程序集元数据。程序集清单包含指定该程序集的版本要求和安全标识所需的所有元数据,以及定义该程序集的范围和解析对资源和类的引用所需的全部元数据。
(2)NamingMainfestResources
要查看一个已经正确嵌入到项目输出程序集中的文件,可以利用SDK工具ildasm.exe,它其实就是MSIL反汇编程序,它能够在你程序集的Mainfest视图里显示所有的嵌入资源。
它在ildasm中显示为.mresource入口,资源名称显示格式如下:
defaultNamespace.folderName.fileName
defaultNamespace可以在项目的属性页面中“应用程序”Tab页面中进行更改。
(3)LoadingMainfestResources
也通过程序来枚举清单,需要利用到System.Reflection.Assembly类的GetMainifestResourceNames方法。另外,还可以检索特定类型的程序集,例如Assembly类还提供了GetAssembly、GetCallingAssembly、GetEntryAssembly和GetExecutingAssembly等。
//Getthistype'sassembly Assemblyasm=this.GetType().Assembly; //Enumeratetheassembly'smanifestresources foreach(stringresourceNameinasm.GetManifestResourceNames()){ MessageBox.Show(resourceName); }
Type为System.Reflection功能的根,也是访问元数据的主要方式。使用Type的成员获取关于类型声明的信息,如构造函数、方法、字段、属性(Property)和类的事件,以及在其中部署该类的模块和程序集。
表示某个类型是唯一的Type对象;即,两个Type对象引用当且仅当它们表示相同的类型时,才引用相同的对象。这允许使用参考等式来比较Type对象。Type类表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。Object.GetType方法返回表示实例类型的Type对象。
如果知道资源的名称,则可以通过Assembly类的方法GetManifestResourceStream方法加载指定的清单资源,资源名称大小写敏感,而且是全称。例如:
//Getthistype'sassembly Assemblyasm=this.GetType().Assembly; //Getthestreamthatholdstheresource //fromthe"ResourcesSample.Azul.jpg"resource //NOTE1:Makesurenottoclosethisstream, //ortheBitmapobjectwillloseaccesstoit //NOTE2:Alsobeverycarefultomatchthecase //ontheresourcenameitself Streamstream= asm.GetManifestResourceStream("ResourcesSample.Azul.jpg"); //Loadthebitmapfromthestream this.BackgroundImage=newBitmap(stream);
(4)MainfestResourceNamespaces
如果传递给GetMainfestResourcesStream方法一个System.Type对象,则它会用此类型的命名空间当作嵌入资源的前缀的一部分,如:
//Loadthestreamforresource"ResourcesSample.Azul.jpg" Streamstream=asm.GetManifestResourceStream(this.GetType(),"Azul.jpg");
Bitmap类也可以直接装载嵌入的资源,如:
//Loadimagefrom"ResourcesApp.Azul.jpg" this.BackgroundImage=newBitmap(this.GetType(),"Azul.jpg");
2.StronglyTypedResources
在清单资源中不包含类型信息,虽然文件带有扩展名,但是类似Bitmap类是根据数据本身来判断类型的。
(1)ApplicationResources(.resx)Files
资源文件(.resx)的主要作用就是记录资源的相应类型信息,由于采用了.NET特定的XML方案(ResX)来保存资源类型信息。一个空的.resx文件也有42行内容,大多数都是方案信息。这个方案允许有许多条目信息,每个都包含name、value,comment,type和MultipurposeInternetMailExtensions(MIME)type。虽然此文件是基于文本的,但是如果要编辑或者阅读,最好还是通过VS2005的资源编辑器来完成。
.resx格式中的名称/值对在XML代码中打包,它描述字符串或对象值。当字符串被添加到.resx文件中时,该字符串的名称被嵌入在<data>标记中,并且值包括在<value>标记内,如以下示例所示。
当一个对象被插入到.resx文件中时,使用相同的<data>和<value>标记来描述该项,但<data>标记要包括类型或MIME类型说明符。类型说明符保留所保存对象的数据类型。如果对象由二进制数据组成,则MIME类型说明符保持所存储的二进制信息的基类型(Base64)。
(2)ManagingResources
资源编辑器支持六类资源:
a.字符串:在带有字符串资源的“名称”、“值”和“注释”列的设置网格中显示字符串。
b.图像:显示所有图像文件(包括.bmp、.jpg和.gif格式)。这些文件在运行时作为Bitmap公开。此类别也包括作为Metafile公开的Windows图元文件。
c.图标
d.音频:显示声音文件(包括.wav、.wma和.mp3文件)。这些文件作为字节数组公开。
e.文件:显示不适合以上类别的任何文件。此视图中的项是作为String公开的文本文件,或是作为字节数组公开的二进制文件。
f.其他 :显示用来添加其他支持字符串序列化的类型(例如,Font、Enum、Color和Point)的设置网格。此网格包含以下列:“名称”、“类型”、“值”和“注释”。
添加资源:
可以通过拖放、菜单选择来添加资源,通过资源编辑器添加到.resx文件的所有资源文件都会放到项目文件夹下的Resources文件夹下,如果不存在则创建。如果将一个已经存在项目里的资源添加到.resx文件中,则这个资源不会被移动或拷贝到Resources文件夹下,因为资源编辑器是通过对文件的引用来管理资源文件,resx文件仅仅存放实际清单资源的类型信息。
删除资源:
通过资源编辑器只能从.resx中移除或者剪切资源,而不能实际删除,因为你只是对资源的元数据进行操作,而并非真正的资源文件(字符串除外,它只能被嵌入)。如果从项目中删除资源文件,但是.resx中的相应元数据还在,这样在编译时就会出现编译异常。
编辑资源:可以通过资源编辑器直接打开相应的编辑程序;
(3)ResourcePersistance
链接资源作为文件存储在项目中;在编译期间,从这些文件中取得资源数据,并将其放到应用程序的清单中。应用程序的资源文件(.resx)只存储指向磁盘上的文件的相对路径或链接。对于嵌入资源,资源数据直接以二进制数据的文本表示形式存储在.resx文件中。在任何一种情况下,资源数据都将编译到可执行文件中。
注意点:字符串资源总是嵌入的资源,无法更改;文件资源总是链接的资源,也无法更改。
如何在嵌入的资源和链接的资源之间进行选择?
-----------------------------------------------------------------
在多数情况下,应该坚持默认的链接资源。但是,在有些情况下选择嵌入的资源会更好。
嵌入的资源:
如果需要在多个项目之间共享应用程序资源(.resx)文件,则嵌入的资源是最佳选择。例如,如果您有一个包含公司徽标、商标信息等类似内容的通用资源文件,则应使用嵌入的资源,这样您只需复制.resx文件,而不用复制关联的资源数据文件。不能直接编辑嵌入的资源。如果试图编辑嵌入的资源,您将会接收到一条消息,提示您将该项转换为链接的资源以便对其进行编辑;此转换是可选的,但建议进行转换。必须导出它们并在外部程序中进行修改,然后将其导回项目中。
链接的资源:
就易用性而言,链接的资源(默认值)是最好的选择。可以在项目内部直接编辑资源,并且可以根据需要轻松添加或移除资源。
-----------------------------------------------------------------
可以通过指定资源的Persistance属性来决定。如果将属性改为嵌入后,将资源文件删除并不会有什么影响,此时如果再改回链接方式,则会在Resources目录下重新创建此资源文件。
如果在资源编辑器下对资源进行管理,则会发现资源的BuildAction,即生成操作都会变为“无”。其实Persistance属性仅仅在设计期间起作用,最终资源数据都将编译到可执行文件中。
(4)UsingTypedResources
*直接使用.resx文件
利用ResXResourceReader类来访问.resx文件;
此类可以枚举XML资源(.resx)文件和流,并读取顺序资源名称和值对,存在于命名空间System.Resources。如果要提取特定条目,则需要先进行遍历寻找。
using(ResXResourceReaderreader= newResXResourceReader(@"C:\MyResources.resx")){ foreach(DictionaryEntryentryinreader){ strings=string.Format("{0}({1})='{2}'", entry.Key,entry.Value.GetType(),entry.Value); MessageBox.Show(s); } }
*使用编译的.resx资源
您可以采用三种不同的方式创建资源文件。如果您的资源将只包含字符串数据,则最简单的方法是手动创建文本文件。如果您的资源将包含对象或字符串与对象的组合,则您必须创建.resx文件或.resources文件。只有.resources文件才应嵌入在公共语言运行库程序集和附属程序集中。资源文件生成器(Resgen.exe)将文本(.txt)文件和基于XML的资源(.resx)文件转换成.resources文件,
资源生成器Resgen.exe:
将.txt文件转换为.resources文件,方法是包装由ResourceWriter类实现的方法。Resgen.exe还包装ResourceReader,这使您可以使用该工具来将.resources文件转换回.txt文件。
编译项目后会将.resx数据嵌入为嵌套资源放在资源清单,例如项目缺省命名空间为A,rest文件为B.resx,则这个嵌套资源容器则为A.B.resources,可以在ildasm中查看。对它的读取利用ResourceReader类,也不支持随机访问。
using(ResourceReaderreader= newResourceReader("MyResources.resources")){ foreach(DictionaryEntryentryinreader){ strings=string.Format("{0}({1})='{2}'", entry.Key,entry.Value.GetType(),entry.Value); MessageBox.Show(s); } }
其实还可以直接通过对清单资源流的访问来操作.resources文件。
Assemblyasm=Assembly.GetExecutingAssembly(); //Loadembedded.resourcesfile using( Streamstream=asm.GetManifestResourceStream( this.GetType(), "MyResources.resources")){ //Findresourcein.resourcesstream using(ResourceReaderreader=newResourceReader(stream)){ foreach(DictionaryEntryentryinreader){ if(entry.Key.ToString()=="MyString"){ //Displaystringresourcevalue MessageBox.Show("MyString="+(string)entry.Value); break; } } } }
以上都需要进行多步操作而且不支持随机访问,但是.NET提供了ResourceManager类来支持对资源的随机访问。
(5)ResourceManager
ResourceManager类可以查找区域性特定的资源,当本地化资源不存在时提供代用资源,并支持资源序列化,它其实也就是对ResourceReader的封装。它由一个嵌入.resource文件初始化:
Assemblyasm=this.GetType().Assembly; ResourceManagerresman=newResourceManager("ResourcesSample.MyResources",asm);
通过ResourceManager的方法,调用方可使用GetObject和GetString两种方法访问特定区域性的资源。
//LoadResourcesSample.MainForm.resourcesfromMainForm.resx ResourceManagerresman=newResourceManager(this.GetType()); //AccesstheMyStringstringresourcefromtheResourceManager //(thesetwotechniquesareequivalentforstrings) strings1=(string)resman.GetObject("MyString"); strings2=resman.GetString("MyString");
(6)强类型资源类
ResourceManager提供了对资源的弱类型方法GetObject来返回资源,需要进行类型转换。但是VS2005和一个自定义工具ResXFileCodeGenerator提供了对这个问题的解决办法。当一个.resx文件被保存时,VS2005会应用自定义工具将其产生一个相应的.Designer.cs文件,此文件提供了一个名字和.resx文件相同的类,这个类所处的命名空间为defaultNamespace.projectPath。
namespaceResourcesSample{ ///<summary> ///Astronglytypedresourceclass,forlookinguplocalized ///strings,etc. ///</summary> //ThisclasswasautogeneratedbytheStronglyTypedResourceBuilder //classviaatoollikeResGenorVisualStudio. //Toaddorremoveamember,edityour.resxfileandthenrerunResGen //withthe/stroption,orrebuildyourVSproject. internalclassMyResources{ staticglobal::System.Resources.ResourceManagerresourceMan; staticglobal::System.Globalization.CultureInforesourceCulture; internalMyResources(){} ///<summary> ///ReturnsthecachedResourceManagerinstanceusedbythis ///class. ///</summary> internalstaticglobal:: System.Resources.ResourceManagerResourceManager{ get{ if((resourceMan==null)){ global::System.Resources.ResourceManagertemp= newglobal::System.Resources.ResourceManager( "ResourcesSample.MyResources", typeof(MyResources).Assembly); resourceMan=temp; } returnresourceMan; } } ///<summary> ///Overridesthecurrentthread'sCurrentUICulturepropertyfor ///allresourcelookupsusingthisstronglytypedresourceclass. ///</summary> internalstaticglobal::System.Globalization.CultureInfoCulture{ get{returnresourceCulture;} set{resourceCulture=value;} } } }
由以上可以看出MyResource类型的两个特征:
a.它通过一个ResourceManager类型的属性提供了对ResourceManager的静态访问,就没必要写之前的创建逻辑了;b.通过一个Culture属性提供了CultureInfo对象实现对本地化信息的静态访问;
提供的每个资源都是强类型静态只读属性。在内部实现中,每个属性都由设计器生成的资源类利用托管的ResourceMananger对象产生的;
//AccessstronglytypedresourcesfromMyResources.resx stringmyString=MyResources.MyString; IconmyIcon=MyResources.MyIcon;
(7)DesignerResources
VS2005提供了整个项目的资源管理。由于Resources.resx文件是从项目的属性页来进行管理的,所以VS2005将它存放到项目的Properties文件夹中。当在项目中添加.resx文件时,ResXFileCodeGenerator工具会自动生成Resources.Designer.cs:
namespaceResourcesSample.Properties{
...
internalclassResources{
...
则可以如下来访问资源:MessageBox.Show(Properties.Resources.MyString);
项目会自动生成一个跟窗体关联的.resx文件,保存类似BackgroundImage和Icon等资源信息。属性窗口可以打开选择资源编辑器,允许选择适当的图片资源。它提供了两种导入和保存资源的方式:作为本地资源;作为项目资源文件。对于窗体,本地资源被嵌入到窗体设计器自动创建的.resx文件中并和窗体关联,如果选择本地资源,则可以直接将图片导入到窗体的资源文件中。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。