Monday, January 09, 2006

C# - Resources – Binary Typed Resources

A Text-Based Typed Resources (.resx xml file) can be compiled into Binary Typed Resources with the following command:
 resgen [resource filename.resx]

 resgen BinaryResourcesForm.resx
The above command will produce a Binary Typed Resources file with extension .resources. The application can load and enumerate the Binary Typed Resources with ResourceReader object from the System.Resources namespace:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Resources;
using System.Collections;

namespace BinaryResourcesApplication {
 public class BinaryResourcesForm: Form {

  // Constructor
  public BinaryResourcesForm() {
   this.SuspendLayout();

   // Load the resources from the resource file 
   // BinaryResources.resources assuming this file 
   // located at the same folder as the application 
   // executable
   using (ResourceReader reader = 
      new ResourceReader(@"BinaryResources.resources")) {

    // Enumerate with a Dictionary object
    foreach (DictionaryEntry entry in reader) {
     string temp = string.Format("
      Name: {0}, // Resource Name (name attribute)
      Value: {1}, // Resoutce Value (value attribute)
      Type: {2}", // Resource Type (type attribute)
      entry.Key, 
      entry.Value,
      entry.Value.GetType());
     MessageBox.Show(temp);
    }
   }

   this.ResumeLayout(false);
  }

  public static void Main() {
   Application.Run(new BinaryResourcesForm());
  }
 }
}
The code above is similar to the Text-Based Typed Resources application, and there is no random access provided by the ResourceReader class. So the application has to loop through all the resources to find the matching entry. The Binary Typed Resources file (.resources file) can be embedded into the application assembly like other resources:
 csc [source file name.cs] /resource:[resource file name]

 csc BinaryResourcesApplication.cs /resource:BinaryResources.resources
The above code will embed the resources into the assembly as Nested Resources. Nested Resources are resources grouped into a named container:

Above example generated by running ildasm:
 ildasm BinaryResourcesApplication.exe
The example shows there are 2 resources embedded into the assembly:
…
.mresource public BinaryResources.resources
{
  // Offset: 0x00000000 Length: 0x00002683
}
.mresource public ufo.gif
{
  // Offset: 0x00002688 Length: 0x00000A01
}
…
The first entry, BinaryResoures.resources is a Named Container for the Binary Typed Resources. Following code shows how to retrieve the resources embedded into this Named Container:
using System;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Resources;
using System.Collections;
using System.Reflection;

namespace BinaryResourcesApplication {
 public class BinaryResourcesForm: Form {

  private Assembly assembly;

  // Constructor
  public BinaryResourcesForm() {
   this.assembly = this.GetType().Assembly;
    
   this.SuspendLayout();
     
   // Load stream from the Named Container (binary resources)
   Stream  stream = 
      this.assembly.GetManifestResourceStream("BinaryResources.resources");
    
   // Pass the stream object to the ResourceReader Constructor
   using (ResourceReader reader = new ResourceReader(stream)) {
     
    // Enumerate the resources container with a Dictionary object 
    foreach (DictionaryEntry entry in reader) {
       
     // Matching entry for Form Caption
     if (entry.Key.ToString() == "FormCaption") {
      this.Text = (string) entry.Value;
     }
    }
   }
        
   // Close Stream object
   stream.Close();
     
   this.ResumeLayout(false);
  }

  public static void Main() {
   Application.Run(new BinaryResourcesForm());
  }
 }
}

No comments: