Resources such as pictures or string tables can be put into resource files or satellite assemblies. Such resources can be very helpful when localizing applications, and .NET has built-in support to search for localized resources.
Before you see how to use resources to localize applications, the next sections discuss how resources can be created and read without looking at language aspects.
Creating Resource Flies
Resource file; can contain such things as pictures and string tables. A resource file is created by using either a normal text file or a . resX file that uses XML. This section starts with a simple text file. A resource that embeds a string table can be created by using a normal text file. The text file just assigns strings to keys. The key is the ame that can be used from a program to get the value. Spaces are allowed
in both keys and values. •
This example shows a simple string table in the file strings. txt:
Title = Professional Ci
Chapter = L~calization
Author = Christian Nagel
Publisher = Wrox Press
When saving text files with Unicode characters, you must save the file with the proper encoding. Select
the Unicode encoding with the Save dialog.
Resource File Generator
The Resource File Generator (Resgen. exe) utility can be used to create a resource file out of strings.txt.Typing
creates the file strings. resources. The resulting resource file can either be added to an assembly as an external file or embedded into the DLLor EXE.Resgen also supports the creation of XML-based . resX resource files. One easy way to build an XMLfile is by using Resgen itself: resgen strings.txt strings.resX
This command creates the XMLresource file strings. resX. You see how to work with XMLresource files in the section “Windows Forms Localization Using Visual Studio” later in this chapter. Since .NET2.0, Resgen supports strongly typed resources. A strongly typed resource is represented by a class that accesses the resource. The class can be created with the /str option of the Resgen utility: resgen str:C#,DemoNamespace,DemoResource,DemoResource.cs strings.resX’
With the option /str, the language, namespace, class name, and the file name for the source code are defined in that order. he Resgen utility does not support adding pictures. With the .NET Framework SDKsamples, you get a
ResXGensample with the tutorials. With ResXGenit is possible to reference pictures in a . resX file. Adding pictures can also be done programmatically by using the Resourcewrit:er or ResXResourceWri ter classes, as you see next.
Instead of using the Resgen utility to build resource files, it’s a simple task to write a program to create resources. The class ResourceWri ter from the namespace System. Resources can be used to write binary resource files; ResXResourceWri ter writes XML-based resource files. Both of these classes support pictures and any other object that is serializable. When yap use the class ResXResourceWri ter, the assembly System. Windows. Forms must be referenced.
In the foll,?wingcode example, you create a ResXResourceWriter object, rw, using a constructor with the file name Demo.resx. After creating an instance, you can add a number of resources of up to 2GBin total size using the AddResource () method of the ResXResourceWri ter class. The first argument of AddResource () specifies the name of the resource and the second argument specifies the value. Apicture resource can be added using an instance of the Image class. To use the Image class, you have to reference the assembly System. Drawing. Youalso add the using directive to open the namespace System. Drawing. ~
Create an Image object by opening the file logo. gif. You will have to copy the picture to the directory of the executable or specify the full path to the picture in the method argument of Image. ToFile ( ) . The us ing statement specifies that the image resource should automatically be disposed at the end of the using block. Additional simple string resources are added to the ResXResourceWri ter object. The Close () method of the ResXResourceWri ter class automatically calls ResXResourceWri ter. Generate () to finally write the resources to the file Demo.resx:
Starting this small program creates the resource file Demo. resx that embeds the image logo. gi f. The resources will now be used in the next example with a Windows application.
Using Resource Flies
You can add resource files to assemblies with the command-line C# compiler csc . exe using the’ /resource option, or directly with Visual Studio 2008. To see how resource files can be used with Visual Studio 2008, create a C# Windows application and name it ResourceDemo. Use the context menu of the Solution Explorer (Add ~ Add Existing Item) to add the previously created resource file Demo. resx to this project. By default, Build Action of this tesource is set to Embedded Resource so that this resource is embedded into the output assembly (see Figure 21-6).
Set the Neutral Language setting of the application to the main language, for example, English (U~ted States), as shown in Figure 21-7.
Changing this setting adds the attribute [NeutralResourceLanguageAttribut:.e] to the file assemblyinfo. cs as you can see here:
Setting this option gives a performance improvement with the ResourceManager because it more quickly finds the resources for en-US that are also used as a default fallback. With this attribute you can also specify the location of the default resource using the second parameter with the constructor. With the enumeration UltimateResourceFallbackLocation you can specify the default resource to be stored in the main assembly or in a satellite assembly (values MainAssembly and Satell i tel.
After building the project, you can check the generated assembly with i Ldasm to see the attribute .mresource in the manifest (see Figure 21-8).. mresource declares the name for the resource in the assembly. If .mresource is declared as public (as in the example), the resource is exported from the assembly and can be used from classes in other assemblies .. mresource private means that the resource is not exported and is available only within the assembly
When you add resources to the assembly using VIsual Studio 2008, the resource is always public, as shown in Figure 21-8.If the assembly generation tool is-used to create assemblies, you can use command-line options to differentiate between adding public and private resources. The option / embed: demo. resources, Y adds the resource as public, whereas / embed: demo. resources, N adds the resource as private.
In your Windows application, you add some text boxes and a picture by dropping Windows Forms elements from the toolbox into the Designer. The values from the resources will be displayed in these Windows Forms elements. Change the Text and Name properties of the text boxes and the labels to the values that you can see in the following code. The name property of the Pic.tureBox control is changed to logo. Figure 21-9 shows the final form in the Forms Designer. The PictureBox control is shown as a rectangle without a grid in the upper-left comer.
To access the embedded resource, use the ResourceManager class from the System. Resources namespace. YQUcan pass the assembly that has the resources as an argument to the constructor of the ResourceManager class. In this example, the resources are embedded in the executing assembly, so pass the result of Assembly. GetExecutingAssembly () as the second argument. The first argument is the root name of the resources. The root name consists of the namespace, with the name of the resource file but without the resources extension. As you saw earlier, ildasm shows the name. All you have to do is remove the file extension resources from the name shown. You can also get the name programmatically using the GetManifestResourceNames () method of the
System. Reflection. Assembly class:
Using the ResourceManager instance rm, you can get all the resources by specifying the key to the methods GetObj ect () and GetString ()
When you run the code, you can see the string and picture resources (see Figure 21-10).
With strongly typed resources, the code written earlier in the constructor of the class ResourceDemoForrn can be simplified; there is no need to instantiate the ResourceManager and access the resources using indexers. Instead, the names of the resources are accessed with properties:
To create a strongly typed resource, the custof Tool property of the’XML-based resource filemust be set to ResXFileCodeGenerator. By setting thisoption, the classDemo (ithas the same name as the ,resource)iscreated.This classhas staticproperties for allthe resources to offera strongly typed resource name. With the implementation of the staticproperties, a ResourceManager object isused that is instantiated on firstaccess and then cached:
Before moving on to the next example, this section concludes with a review of the classes contained in the System. Resources namespace that deal with resources
¤ The ResourceManager class can be used to get resources for the current culture from assemblies or resource files. Using the ResourceManager, you can also get a ResourceSet for a particular culture.
¤ A ResourceSet represents the resources for a particular culture. When a r:esourceSet instance is created, it enumerates over a class, implementing the interface IResourceReader, and it stores all resources in a Hashtable.
¤ The interface IResourceReader is used from the ResourceSet to enumerate resources. The class ResourceReader implements this interface.
¤ The class Resourcewri ter is used to create a resource file. ResourceWriter implements the interface IResourceWri ter.
¤ ResXResourceSet, ResXResourceReader, and ResXResourceWri ter are similar to ResourceSet, ResourceReader, and ResourceWri ter; however, they are used to create an XML-based resource file. resX instead of a binary file. You can use ResXFileRef to make a link to a resource instead of embedding it inside an XMLfile.