Because XML resource (.resx) files must
consist of well-defined XML, including a header that must follow a
specific schema followed by data in name/value pairs, you may find that
creating these files manually is error-prone. As an alternative, you can
create .resx files programmatically by using types and members in the
.NET Framework Class Library. You can also use the .NET Framework Class
Library to retrieve resources that are stored in .resx files. This topic
explains how you can use the types and members in the System.Resources namespace to work with .resx files.
Caution |
---|
There are also ways to work with .resx files other than programmatically. When you add a resource file to a Visual Studio project, Visual Studio provides an interface for creating and maintaining a .resx file, and automatically converts the .resx file to a .resources file at compile time. You can also use a text editor to manipulate a .resx file directly. However, to avoid corrupting the file, be careful not to modify any binary information that is stored in the file. |
You can use the System.Resources.ResXResourceWriter class to create a .resx file programmatically, by following these steps:
The
following example creates a .resx file named CarResources.resx that
stores six strings, an icon, and two application-defined objects (two Automobile objects). Note that the Automobile class, which is defined and instantiated in the example, is tagged with the SerializableAttribute attribute.
You cannot embed a
.resx file in a runtime executable or compile it into a satellite
assembly. You must convert your .resx file into a binary resource
(.resources) file by using the Resource File Generator (Resgen.exe).
The resulting .resources file can then be embedded in an application
assembly or a satellite assembly. For more information, see Creating Resource Files.
- Instantiate a ResXResourceWriter object by calling the ResXResourceWriter.ResXResourceWriter(String) method and supplying the name of the .resx file. The file name must include the .resx extension. If you instantiate the ResXResourceWriter object in a using block, you do not explicitly have to call the ResXResourceWriter.Close method in step 3.
- Call the ResXResourceWriter.AddResource method for each resource you want to add to the file. Use the overloads of this method to add string, object, and binary (byte array) data. If the resource is an object, it must be serializable.
- Call the ResXResourceWriter.Close method to generate the resource file and to release all resources. If the ResXResourceWriter object was created within a using block, resources are written to the .resx file and the resources used by the ResXResourceWriter object are released at the end of the using block.
Caution |
---|
Do not use resource files to store passwords, security-sensitive information, or private data. |
using System; using System.Drawing; using System.Resources; [Serializable()] public class Automobile { private string carMake; private string carModel; private int carYear; private int carDoors; private int carCylinders; public Automobile(string make, string model, int year) : this(make, model, year, 0, 0) { } public Automobile(string make, string model, int year, int doors, int cylinders) { this.carMake = make; this.carModel = model; this.carYear = year; this.carDoors = doors; this.carCylinders = cylinders; } public string Make { get { return this.carMake; } } public string Model { get {return this.carModel; } } public int Year { get { return this.carYear; } } public int Doors { get { return this.carDoors; } } public int Cylinders { get { return this.carCylinders; } } } public class Example { public static void Main() { // Instantiate an Automobile object. Automobile car1 = new Automobile("Ford", "Model N", 1906, 0, 4); Automobile car2 = new Automobile("Ford", "Model T", 1909, 2, 4); // Define a resource file named CarResources.resx. using (ResXResourceWriter resx = new ResXResourceWriter(@".\CarResources.resx")) { resx.AddResource("Title", "Classic American Cars"); resx.AddResource("HeaderString1", "Make"); resx.AddResource("HeaderString2", "Model"); resx.AddResource("HeaderString3", "Year"); resx.AddResource("HeaderString4", "Doors"); resx.AddResource("HeaderString5", "Cylinders"); resx.AddResource("Information", SystemIcons.Information); resx.AddResource("EarlyAuto1", car1); resx.AddResource("EarlyAuto2", car2); } } }
Important |
---|
You can also use Visual Studio to create .resx files. At compile time, Visual Studio uses the Resource File Generator (Resgen.exe) to convert the .resx file to a binary resource (.resources) file, and also embeds it in either an application assembly or a satellite assembly. |
In
some cases, you may want to retrieve all resources, instead of a
specific resource, from a .resx file. To do this, you can use the System.Resources.ResXResourceReader class, which provides an enumerator for all resources in the .resx file. The System.Resources.ResXResourceReader class implements IDictionaryEnumerator, which returns a DictionaryEntry object that represents a particular resource for each iteration of the loop. Its DictionaryEntry.Key property returns the resource's key, and its DictionaryEntry.Value property returns the resource's value.
The following example creates a ResXResourceReader object for the CarResources.resx file created in the previous example and iterates through the resource file. It adds the two Automobile objects that are defined in the resource file to a System.Collections.Generic.List<T> object, and it adds five of the six strings to a SortedList object. The values in the SortedList object are converted to a parameter array, which is used to display column headings to the console. The Automobile property values are also displayed to the console.
The following example creates a ResXResourceReader object for the CarResources.resx file created in the previous example and iterates through the resource file. It adds the two Automobile objects that are defined in the resource file to a System.Collections.Generic.List<T> object, and it adds five of the six strings to a SortedList object. The values in the SortedList object are converted to a parameter array, which is used to display column headings to the console. The Automobile property values are also displayed to the console.
using System; using System.Collections; using System.Collections.Generic; using System.Resources; public class Example { public static void Main() { string resxFile = @".\CarResources.resx"; List<Automobile> autos = new List<Automobile>(); SortedList headers = new SortedList(); using (ResXResourceReader resxReader = new ResXResourceReader(resxFile)) { foreach (DictionaryEntry entry in resxReader) { if (((string) entry.Key).StartsWith("EarlyAuto")) autos.Add((Automobile) entry.Value); else if (((string) entry.Key).StartsWith("Header")) headers.Add((string) entry.Key, (string) entry.Value); } } string[] headerColumns = new string[headers.Count]; headers.GetValueList().CopyTo(headerColumns, 0); Console.WriteLine("{0,-8} {1,-10} {2,-4} {3,-5} {4,-9}\n", headerColumns); foreach (var auto in autos) Console.WriteLine("{0,-8} {1,-10} {2,4} {3,5} {4,9}", auto.Make, auto.Model, auto.Year, auto.Doors, auto.Cylinders); } } // The example displays the following output: // Make Model Year Doors Cylinders // // Ford Model N 1906 0 4 // Ford Model T 1909 2 4
In addition to enumerating the items in a .resx file, you can retrieve a specific resource by name by using the System.Resources.ResXResourceSet class. The ResourceSet.GetString(String) method retrieves the value of a named string resource. The ResourceSet.GetObject(String)
method retrieves the value of a named object or binary data. The method
returns an object that must then be cast (in C#) or converted (in
Visual Basic) to an object of the appropriate type.
The following example retrieves a form's caption string and icon by their resource names. It also retrieves the application-defined Automobile objects used in the previous example and displays them in a DataGridView control.
The following example retrieves a form's caption string and icon by their resource names. It also retrieves the application-defined Automobile objects used in the previous example and displays them in a DataGridView control.
using System; using System.Collections.Generic; using System.Drawing; using System.Resources; using System.Windows.Forms; public class CarDisplayApp : Form { private const string resxFile = @".\CarResources.resx"; Automobile[] cars; public static void Main() { CarDisplayApp app = new CarDisplayApp(); Application.Run(app); } public CarDisplayApp() { // Instantiate controls. PictureBox pictureBox = new PictureBox(); pictureBox.Location = new Point(10, 10); this.Controls.Add(pictureBox); DataGridView grid = new DataGridView(); grid.Location = new Point(10, 60); this.Controls.Add(grid); // Get resources from .resx file. using (ResXResourceSet resxSet = new ResXResourceSet(resxFile)) { // Retrieve the string resource for the title. this.Text = resxSet.GetString("Title"); // Retrieve the image. Icon image = (Icon) resxSet.GetObject("Information", true); if (image != null) pictureBox.Image = image.ToBitmap(); // Retrieve Automobile objects. List<Automobile> carList = new List<Automobile>(); string resName = "EarlyAuto"; Automobile auto; int ctr = 1; do { auto = (Automobile) resxSet.GetObject(resName + ctr.ToString()); ctr++; if (auto != null) carList.Add(auto); } while (auto != null); cars = carList.ToArray(); grid.DataSource = cars; } } }
No comments:
Post a Comment