Localization and Satellite Assemblies


At this point, you should have a good idea of how to create an assembly, what an assembly is, and how to program against it. In addition, you've seen how to embed resources such as XML files or images into the assembly and use the GetManifestResourceStream method to obtain a stream that can be used to view the resource. The next section of this chapter takes a look at what Visual Studio .NET calls assembly resource files.

An assembly resource file is essentially an XML file that contains resources. These resources can be strings, bitmaps, images, XMLwhatever you like. To retrieve data from a resource file, you must supply a string identifier. When Visual Studio .NET has a .resx file, you can double-click it to pull up an editor that enables you to edit it in either an XML view or a data view. Every resource has a name that is used to retrieve it. That name is given to an instance of the ResourceManager class to obtain a resource. Here is an example of retrieving an integer from an assembly resource file that is part of a project:

 ResourceManager rm = new ResourceManager("MyApp.MyResources",     Assembly.GetExecutingAssembly()); int myint = (int)rm.GetObject("mynumber"); 

This should look pretty similar to the code to retrieve the embedded XML stream. The difference between the assembly resource file and doing it manually (as we did earlier) is that the assembly resource file supports localization. In other words, in addition to each resource being identifiable by name, it is also identifiable by culture.

The logic for finding a resource is actually fairly complex, but also extremely helpful. It works in a hierarchy, starting from most-specific culture to least-specific culture. For example, if your application defines strings in the neutral French culture, but someone's application is running in a location that speaks French but is not in France, the ResourceManager will still be able to find the appropriate French strings. If your application defines French resources as well as resources for the neutral (empty string) culture, people who are in non-French locations will still be able to locate the neutral resources and use those.

Satellite Assemblies

A satellite assembly is one that contains nothing but resources. It is usually created automatically for you by Visual Studio .NET, but you can do it manually using the command-line compilation tools. There are quite a few benefits of satellite assemblies, some of which are as follows:

  • Resources can be added dynamically to the application after deployment.

  • Modification of localized resources in satellite assemblies does not require recompilation of the application.

  • Only those assemblies for the current culture are loaded, reducing memory overhead.

The model by which the Common Language Runtime locates localized resources is referred to as the spoke-and-hub model. As I said, it is a recursive descending hierarchy to locate the most appropriate resources given the current thread's culture. Figure 12.4 illustrates the spoke-and-hub model for resource location. When Visual Studio .NET creates satellite assemblies, they are placed in directories corresponding to spokes in the model shown in Figure 12.4.

Figure 12.4. The spoke-and-hub model for resource localization.


Now that you know how satellite assemblies work and what they do, you can create some. To do this, you'll create three separate assembly resource files. Right-click the AssemblyIntro project and add a new item of type Assembly Resource File. Call these three files Strings.resx, Strings.hi.resx, and Strings.fr.resx. For the first file, add a resource string called greeting, with a value of Hello and a type of System.String. Make sure that you move the cursor off the current row before you save it, or the IDE will erase the entry. Table 12.1 shows how you should set up the various strings in each file.

Table 12.1. Multilingual Greetings in a .resx File

File

Name

Value

Type

Strings.resx

greeting

Hello

System.String

Strings.hi.resx

greeting

Namaste

System.String

Strings.fr.resx

greeting

Bonjour

System.String


It is vitally important that the string have the same name across all the different cultures. If you've followed Table 12.1, you should now have a greeting text in English, Hindi, and French.

Now write some code that accesses these strings. First, add the following method to the AssemblyTool class:

 public static string GetResourceString( string id ) {   ResourceManager rm =      new ResourceManager(      "SAMS.CSharpUnleashed.Chapter12.AssemblyIntro.Strings",       Assembly.GetExecutingAssembly());   return rm.GetString( id ); } 

Note how the entire namespace is used as the first argument to the ResourceManager. Also note that the code didn't specify the culture. If no culture is specified manually, the ResourceManager class will use the current thread's culture.

Now add the following lines of code to the Class1 class in the Harness console application as shown in Listing 12.4 (the additions have been highlighted).

Listing 12.4. The Revised Class1 Class
 using System; using System.Threading; using System.Globalization; using SAMS.CSharpUnleashed.Chapter12.AssemblyIntro; namespace Harness {   /// <summary>   /// Summary description for Class1.   /// </summary>   class Class1   {     /// <summary>     /// The main entry point for the application.     /// </summary>     [STAThread]     static void Main(string[] args)     {       Console.WriteLine( AssemblyTool.GetAssemblyInfo() );       Console.WriteLine("--");       Console.WriteLine( AssemblyTool.GetDataNodeValue(21) );       Console.WriteLine( AssemblyTool.GetDataNodeValue(35) );       Console.WriteLine( AssemblyTool.GetDataNodeValue(50) );       Console.WriteLine("--");       Console.WriteLine( AssemblyTool.GetResourceString( "greeting" ) );       CultureInfo ci = new CultureInfo("hi-IN");       Thread.CurrentThread.CurrentCulture = ci;       Thread.CurrentThread.CurrentUICulture = ci;       Console.WriteLine( AssemblyTool.GetResourceString( "greeting" ) );       ci = new CultureInfo("fr-FR");       Thread.CurrentThread.CurrentCulture = ci;       Thread.CurrentThread.CurrentUICulture = ci;       Console.WriteLine( AssemblyTool.GetResourceString( "greeting" ) );       Console.ReadLine();     }   } } 

As expected, you see a greeting in three different languages when you run the application. Before moving on to AppDomains, take a look at the bin\debug directory of the application. Figure 12.5 shows that the French and Hindi satellite assemblies have actually been stored in separate directories.

Figure 12.5. The debug directory, showing the directories for satellite assemblies.




    Visual C#. NET 2003 Unleashed
    Visual C#. NET 2003 Unleashed
    ISBN: 672326760
    EAN: N/A
    Year: 2003
    Pages: 316

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net