ResourceManager.CreateFileBasedResourceManager


Embedded inside the ResourceManager class is a second resource manager that, instead of reading resources from an assembly, reads resources from stand-alone resource files. If you have seen Harry Potter and the Sorcerer's Stone, you can think of this resource manager as the parasitic Lord Voldemort sharing the same body as Professor Quirrell. To make a distinction between the two resource managers that inhabit the same ResourceManager class, I refer to them as "assembly-based" resource managers and "file-based" resource managers. This file-based resource manager can be created using the static ResourceManager.CreateFileBasedResourceManager method:

 ResourceManager resourceManager =     ResourceManager.CreateFileBasedResourceManager(     "Strings", ".", null); 


The first parameter is the base name of the resources file. This is the filename without the culture and without the file extension. The second parameter is the directory in which the file is located. The third parameter is a Type that is used to create new ResourceSets. Hereafter, this file-based resource manager is used and behaves in the exact same way as an assembly based resource manager, so to get a string, we call GetString:

 MessageBox.Show(resourceManager.GetString("Hello")); 


If the CurrentUICulture hasn't been set, this looks for a file called "Strings.resources" in the same directory as the executable. If the CurrentUI-Culture is "fr-FR", it looks for a file called "Strings.fr-FR.resources".

Of course, you need to create the resources file. If you are starting from a resx file, you can create it using the .NET Framework resgen utility:

 resgen Strings.resx 


This creates Strings.resources. You then need to move the resources file into the same directory as the executable assembly. The problem with this approach is that it requires the developer to invoke resgen manually and to copy the resulting file. It's a minor effort for a single file, but it is easily forgotten. A better solution is one that is part of the build process. The next three sections cover this process for Windows Forms, ASP.NET 2.0, and ASP.NET 1.1, respectively.

Incorporating resgen into the Build Process for Windows Forms

You can incorporate resgen into the build process so that it is run automatically. In either Visual Studio 2005 or Visual Studio 2003, right-click the project in Solution Explorer, select Properties, and click on the Build Events tab (see Figure 12.1).

Figure 12.1. The Project's Build Events in Visual Studio 2005


In the "Post-build event command line:," you can enter a command to execute after the build process. Enter the following command (on a single line):

 "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\resgen"     C:\Examples\WindowsApplication1\Strings.resx     C:\Examples\WindowsApplication1\bin\debug\     Strings.resources 


(For Visual Studio 2003, use the .NET Framework SDK 1.1 bin folder, which is typically C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin).

Click OK. From here on, whenever you do a successful build, this command will be run after the build has completed. Of course, this uses hard-coded paths, so a better solution is to use macros to refer to the project directory and the target directory:

 "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\resgen"     $(ProjectDir)\Strings.resx     $(TargetDir)\Strings.resources 


This is fine if you just want to compile a single resource, but that's probably not the case for most applications. A better approach is to create a script file and put this command along with the others in the script file.

Incorporating resgen into the Build Process in ASP.NET 2.0

ASP.NET 2.0 applications do not have a project file; consequently, the solution of using Build Events cannot be used. The best option for ASP.NET 2.0 applications is to use Web Deployment Projects. Web Deployment Projects are separate projects that are added to ASP.NET 2.0 solutions. A Web Deployment Project is an MSBuild project for a Web site. Among the many additional features that Web Deployment Projects offer is the capability to add custom pre- and post-build steps. Web Deployment Projects are an add-in package for Visual Studio 2005 and can be downloaded from http://msdn.microsoft.com/asp.net/reference/infrastructure/wdp/default.aspx. To add steps to call resgen to compile resx files, install Web Deployment Projects. In Visual Studio 2005, open the Web site, select Solution Explorer, right-click the site, and select the new menu item "Add Web Deployment Project...". In the Add Web Deployment Project dialog, enter a name and location for the Web Deployment Project and click OK. The Web Deployment Project is an MSBuild file with an extension of .wdproj. To open this file, right-click it in Solution Explorer and select Open Project File. Toward the bottom of the file, you will find the following section:

 <Target Name="BeforeBuild"> </Target> 


By default, this section is commented out, so move it outside the commented region. Finally, you can add the GenerateResource build task to this section to compile the resources. GenerateResource is the MSBuild task that offers similar functionality to resgen.

Incorporating resgen into the Build Process in ASP.NET 1.1

Incorporating resgen into the ASP.NET 1.1 build process requires a little trickery with creating a Visual C++ project, but don't worry; there's no C++ involved in this process. Although this approach works equally well in Windows Forms application in both Visual Studio 2005 and Visual Studio 2003, I recommend using Visual Studio Build Events instead. To incorporate resgen into the build process for a solution, right-click the solution; select Add, New Project...; in Project Types, select Visual C++ Projects; in Templates, select Makefile Project; in Name, enter BuildResources (see Figure 12.2); and click OK.

Figure 12.2. Add New Makefile Project in Visual Studio 2003


Click Finish to close the wizard. In Solution Explorer, you can delete the "Source Files", "Header Files", and "Resource Files" folders and readme.txt. Add a new text file to the project (right-click the BuildResources project; select Add, New Item...; select Text File (.txt); enter BuildResources.bat in the name; and click Open. In BuildResources.bat, add one of the following two commands, according to your version of Visual Studio:

 call "C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\ v1.1\Bin\resgen"     C:\Inetpub\wwwroot\WebApplication1\Strings.resx     C:\Inetpub\wwwroot\WebApplication1\bin\Strings.resources call "C:\Program Files\Microsoft Visual Studio 8\SDK\ v2.0\Bin\resgen"     C:\Inetpub\wwwroot\WebApplication1\Strings.resx     C:\Inetpub\wwwroot\WebApplication1\bin\Strings.resources 


Right-click the BuildResources project, select Properties, select NMake, and enter BuildResources.bat in the "Build Command Line" and "Rebuild All Command Line" (see Figure 12.3).

Figure 12.3. Specifying NMake Properties


Now, whenever you do a build in Visual Studio, this new make project will be built and BuildResources.bat will be executed, running resgen and building the resources files.

ResourceManager.CreateFileBasedResourceManager in Practice

So what the file-based resource manager gives us is the capability to read from .resources files instead of from an assembly. Unfortunately, there is a limitation to this approach, and that is that the .resources files are kept open after they have been read. This means that they cannot be updated until either the ResourceManager.Release AllResources method is called or the underlying ResourceSets get garbage collected. In a Web application, typically this means having to shut down the Web server; therefore, this file-based resource manager is impractical.

In addition to this limitation, another problem faces Windows Forms applications. Recall that when you set Form.Localizable to true, a new line of code is added to the InitializeComponent method to initialize a resource manager:

 // Visual Studio 2003 System.Resources.ResourceManager resources = new     System.Resources.ResourceManager(typeof(Form1)); // Visual Studio 2005 System.ComponentModel.ComponentResourceManager resources = new     System.ComponentModel.ComponentResourceManager(typeof(Form1)); 


Clearly, this is initializing an assembly-based resource manager, not a file-based resource manager. There are two solutions to this problem. The first is to create a linked resource assembly; the second is covered later in this chapter in the ResourceManagerProvider section. A linked resource assembly is an assembly that contains links to stand-alone .resources file. The resource assemblies that we have seen and used so far all contain embedded resources; that is, the resources have been embedded in the assembly, and the stand-alone .resources files are not needed at runtime. A linked assembly doesn't embed the resource files, but instead references or "links" to them. See Chapter 14, "The Translator," for details of creating a linked assembly. Functionally, there is no difference between the two solutions, but it does solve the problem of Visual Studio hard-wiring a reference to the resource manager class. Now we can let Visual Studio write code to create a ResourceManager/ ComponentResourceManager and have it use our linked assembly. The linked assembly still uses the stand-alone .resources files, but we haven't had to call the ResourceManager.CreateFileBasedResourceManager method to use them; therefore, Visual Studio's generated code still works. Unfortunately, using a linked resource assembly doesn't solve the problem that the resource manager still locks the .resources files.




.NET Internationalization(c) The Developer's Guide to Building Global Windows and Web Applications
.NET Internationalization: The Developers Guide to Building Global Windows and Web Applications
ISBN: 0321341384
EAN: 2147483647
Year: 2006
Pages: 213

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