梦想与现实的落差,就是我们离成功的距离!!

博客园 首页 新随笔 联系 订阅 管理


资源与本地化(Resource and Localization)

原文地址:http://msdn.microsoft.com/msdnmag/issues/06/05/BasicInstincts/

在基于Microsoft® .NET框架的应用程序中,你有两种方法来利用诸如字符串,图片,基于文本的文件等资源,你可以把它们之间嵌入应用程序中或者从外部文件中加载。当你选择的是从外部文件中加载而不是从嵌入资源时,必选随同程序集一起分发该文件,你也必需确保应用程序中的代码在运行时能确定正确路径加载资源文件,如果.exe文件与曾经依赖的文件分开了,这方法会引发问题。

采用嵌入选项并把你需要的资源直接编译进程序集使用它们,这样使得分发更加可靠并减少错误发生。这个月我们将讨论资源的使用,怎样和为什么你可以嵌入一个资源,以及在.NET中资源文件的角色?

嵌入一个资源

让我们从一个小实例开始了解如何完成资源嵌入。假设你愿意在Windows Form应用程序中嵌入一个叫LitwareLogo.png图片。开始你把文件加入Visual Studio® 工程中,然后,从文件的属性表单中,你把编译行为( Build Action)设定成嵌入资源(Embedded Resource,如图1所示。完成这些后,你以及指示Visual Studio把该文件嵌入输出程序集.exe文件的物理图片中。


Figure 1 Set Build Action

一旦你把一个文件嵌入为资源,你必需学会在运行时怎样访问它,检查下面的代码片断,它包含一个当前程序集对象的引用,然后调用GetManifestResourceStream方法获取访问嵌入文件的流。这段代码假设你已经导入了System.ReflectionSystem.IO名称空间:

'*** get current Assembly object.

Dim asm As Assembly = Assembly.GetExecutingAssembly()

'*** load embedded resource into stream

Dim ResourceName As String = "LitwareSmartClient.LitwareLogo.png"

Dim str As Stream = asm.GetManifestResourceStream(ResourceName)

    '*** convert stream into image and load in    '*** picture box

    Dim img As Image = Image.FromStream(str)

    PictureBox1.Image = img

如你所见,Assembly对象公开了GetManifestResourceStream方法,它允许你一个传入一个惟一标识嵌入资源的字符串形式的资源名称。注意,资源名称是大小写敏感的即使你使用的是大小写不敏感的语言例如Visual Basic® , 在实例中,代码调用Image.FromStream方法把包含图片文件的流转换成一个能被PictureBox控件加载的图片对象。

除了嵌入图片文件之外,它还能嵌入例如XML,SQL或者JavaScript之类的基于文本的文件。如果你对使用Visual Basic连接XML,SQL,或者JavaScript的字符串片段感到单调乏味,那么这些嵌入资源就使得你的生活简单多了。

例如,让我们假定你有一个很大的你的应用程序需要的XML文档,SQL语句,或者JavaScript方法。你可以在Visual Studio工程中把它们作为独立的.xml文件,.sql文件,或者.js文件来维护。这样你可以得到一些好处,例如Visual Studio的代码着色、语句自动完成功能,你也可以充分利用Visual Studio的针对XML文件的架构驱动(schema-driven)智能感知功能。所有这些要求你把这些资源文件嵌入输出的程序集,并用你已经看到过的方法去访问它们。例如你已经在一个基于Windows Forms的应用程序中嵌入了一个SQL文件和XML文件,你能像图2中代码那样去访问。Figure 2.


资源文件

你刚刚已经看过的技术涉及到直接把把资源文件嵌入进程序集并使用程序集类所支持的GetManifestResourceStream方法去加载它们。但是在.NET中有另一种选择,这就是资源文件(Resource Files),它使得在很多场景下处理资源更加容易。并且,如你等下就要看到的,Visual Studio 2005在碰到资源和本地化应用协同工作的时候提供了一些便利。


Working with Resource Files与资源文件协作

.NET中,资源文件能用作嵌入程序集的资源,使用资源文件的其中的一个关键好处就是应用程序中所有的语言和特定的本地元素或者这种如说明和用户消息的类库DLL能从你的应用程序代码中分离出去。为了做到这点,你需要为你需要支持的每种语言建立单独的资源文件, 实际的资源文件是一种基于文本的包含XML.resx为扩展名的。3展示了在一个资源文件中XML数据的一个缩减样本的示例。

虽然图中的XML片段不是一个完整的资源文件,但它给你一个总体概念,在一个资源文件中会有些什么。你可以使用一个叫做资源文件生成器(Resgen.exe)的基于.NET的实用工具把资源文件编译入一个二进制的映像。典型地被编译好的资源文件的扩展名为.resource。例如公司一个名叫Litware的开发人员能建立一个名称为LitwareString.resx的资源文件,并通过执行如下在一个批处理文件或Visual Studio命令提示中的命令把它编译进一个名称为LitwareString.resource的二进制映像:

RESGEN.EXE LitwareStrings.resx LitwareStrings.resources

在你把一个基于文本的.resx文件编译进一个二进制的.resource文件中后,它仍然不能被使用,相反,你必需进一步把这个二进制文件编译进一个.NET程序集之后才能从一个应用程序中使用它,这个能用另一个叫做程序集连接器(Al.exe)的.NET工具完成这事。例如,为了把LitwareStrings.resources编译进它自己的程序集DLL,你可以从一个批处理文件或Visual Studio 2005的命令提示框中运行下面的命令行指示:

AL.EXE /t:library

 /out:LitwareStrings.resources.dll

 /link:LitwareStrings.resources

 

一旦你已经把一个资源文件编译进一个.NET程序集中,你就能使用RsourceManager类访问内部资源,该类定义在System.Resource名称空间下。下面展示了一个简单用ResourceManager类访问一个字符串资源的代码示例:

Dim asm As Assembly = Assembly.Load("LitwareStrings.resources")

Dim rm As New System.Resources.ResourceManager("LitwareStrings", asm)

Dim caption As String = rm.GetString("MainFormCaption")

Resgen.exe 也能被用来生成一个强类型的资源类,该类公开了一些属性以便能容易地访问内部的资源。例如为了在Visual Basic中生成一个强类型资源类,你能在调用Resgen.exe时在命令行增加/str参数并设值为“vb”:

RESGEN.EXE LitwareStrings.resx LitwareStrings.resources /str:vb

这个命令行指示生成一个Visual Basic 源文件名称为LitwareStrings.vb。该源文件包含了一个名为LitwareStrings的类,在该类中,有代码使用ResourceManager实现了类似如下的强类型属性:

Shared ReadOnly Property MainFormCaption() As String

  Get

    Return ResourceManager.GetString("MainFormCaption", resourceCulture)

  End Get

End Property

我仅仅很快地逐步通过在高层次解释如何把资源文件编译进程序集以及如何使用ResourceManager类和强类型资源类来访问它们。这应该给你一个关于怎样结合单独块更好的主意。

这儿我不想花更多的时间在低层次的资源文件的细节上,因为当你开始本地化应用程序和类库DLL时,你不会被要求来处理那些细节。那是因为Visual Studio 2005Visual Basic在后台提供了许多有价值的便利之处。然而,要紧记当你正在本地化大规模开发工程时,你也许不得不直接与Resgen.exeAl.exe和其它一些.NET实用工具和类打交道。

未完待续!
posted on 2006-05-16 16:37  叶漂  阅读(3061)  评论(0编辑  收藏