KGy SOFT

ResXResourceManager Class

KGy SOFT Core Libraries Help
Represents a resource manager that provides convenient access to culture-specific XML resources (.resx files) at run time. New elements can be added as well, which can be saved into the .resx files.
See the Remarks section for examples and for the differences compared to ResourceManager class.
Inheritance Hierarchy

SystemObject
  System.ResourcesResourceManager
    KGySoft.ResourcesResXResourceManager

Namespace:  KGySoft.Resources
Assembly:  KGySoft.CoreLibraries (in KGySoft.CoreLibraries.dll) Version: 5.0.0-rc.1
Syntax

[SerializableAttribute]
public class ResXResourceManager : ResourceManager, 
	IExpandoResourceManager, IDisposable

The ResXResourceManager type exposes the following members.

Constructors

  NameDescription
Public methodResXResourceManager(Type)
Creates a new instance of ResXResourceManager class that looks up resources in resource XML files based on information from the specified type object.
Public methodResXResourceManager(String, CultureInfo)
Initializes a new instance of the ResXResourceManager class that looks up resources in resource XML files based on the provided baseName.
Public methodResXResourceManager(String, Assembly)
Initializes a new instance of the ResXResourceManager class that looks up resources in resource XML files based on the provided baseName.
Top
Properties

  NameDescription
Public propertyBaseName
Gets the root name of the resource files that the ResourceManager searches for resources.
(Inherited from ResourceManager.)
Public propertyCloneValues
Gets or sets whether GetObject and GetMetaObject methods return always a new copy of the stored values.
Default value: .
Protected propertyFallbackLocation
Gets or sets the location from which to retrieve default fallback resources.
(Inherited from ResourceManager.)
Public propertyIgnoreCase
Gets or sets a value that indicates whether the resource manager allows case-insensitive resource lookups in the GetString(String) and GetObject(String) methods.
(Inherited from ResourceManager.)
Public propertyIsDisposed
Gets whether this ResXResourceManager instance is disposed.
Public propertyIsModified
Gets whether this ResXResourceManager instance has modified and unsaved data.
Public propertyResourceSetType
Gets the type of the resource set object that the resource manager uses to construct a ResourceSet object.
(Inherited from ResourceManager.)
Public propertyResXResourcesDir
Gets or sets the relative path to .resx resource files.
Default value: Resources
Public propertySafeMode
Gets or sets whether the ResXResourceManager works in safe mode. In safe mode the retrieved objects are not deserialized automatically.
See the Remarks section for details.
Default value: .
Public propertyThrowException
Gets or sets whether a MissingManifestResourceException should be thrown when a resource .resx file is not found even for the neutral culture.
Default value: .
Top
Methods

  NameDescription
Public methodDispose
Disposes the resources of the current instance.
Protected methodDispose(Boolean)
Releases unmanaged and - optionally - managed resources.
Public methodEquals
Determines whether the specified object is equal to the current object.
(Inherited from Object.)
Protected methodFinalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(Inherited from Object.)
Public methodGetExpandoResourceSet
Retrieves the resource set for a particular culture, which can be dynamically modified.
Public methodGetHashCode
Serves as the default hash function.
(Inherited from Object.)
Public methodGetMetaObject
Returns the value of the specified non-string metadata for the specified culture.
Public methodGetMetaStream
Returns a MemoryStream instance from the metadata of the specified name and culture.
Public methodGetMetaString
Returns the value of the string metadata for the specified culture.
Public methodGetObject(String)
Returns the value of the specified resource.
See the Remarks section of the ResXResourceManager class for examples.
(Overrides ResourceManagerGetObject(String).)
Public methodGetObject(String, CultureInfo)
Gets the value of the specified resource localized for the specified culture.
See the Remarks section of the ResXResourceManager class for examples.
(Overrides ResourceManagerGetObject(String, CultureInfo).)
Protected methodGetResourceFileName
Generates the name of the resource file for the given CultureInfo object.
(Overrides ResourceManagerGetResourceFileName(CultureInfo).)
Public methodGetResourceSet
Retrieves the resource set for a particular culture.
(Overrides ResourceManagerGetResourceSet(CultureInfo, Boolean, Boolean).)
Public methodGetStream(String)
Returns a MemoryStream instance from the resource of the specified name.
Public methodGetStream(String, CultureInfo)
Returns a MemoryStream instance from the resource of the specified name and culture.
Public methodGetString(String)
Returns the value of the specified string resource.
(Overrides ResourceManagerGetString(String).)
Public methodGetString(String, CultureInfo)
Returns the value of the string resource localized for the specified culture.
(Overrides ResourceManagerGetString(String, CultureInfo).)
Public methodGetType
Gets the Type of the current instance.
(Inherited from Object.)
Protected methodInternalGetResourceSet
Provides the implementation for finding a resource set.
(Overrides ResourceManagerInternalGetResourceSet(CultureInfo, Boolean, Boolean).)
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Public methodReleaseAllResources
Disposes all of the cached ResXResourceSet instances and releases all resources.
(Overrides ResourceManagerReleaseAllResources.)
Public methodRemoveMetaObject
Removes a metadata object from the current ResXResourceManager with the specified name for the specified culture.
Public methodRemoveObject
Removes a resource object from the current ResXResourceManager with the specified name for the specified culture.
Public methodSaveAllResources
Saves all already loaded resources.
Public methodSaveResourceSet
Saves the resource set of a particular culture if it has been already loaded.
Public methodSetMetaObject
Adds or replaces a metadata object in the current ResXResourceManager with the specified name for the specified culture.
Public methodSetObject
Adds or replaces a resource object in the current ResXResourceManager with the specified name for the specified culture.
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
Top
Fields

  NameDescription
Protected fieldBaseNameField
Specifies the root name of the resource files that the ResourceManager searches for resources.
(Inherited from ResourceManager.)
Protected fieldMainAssembly
Specifies the main assembly that contains the resources.
(Inherited from ResourceManager.)
Protected fieldResourceSets Obsolete.
Contains a Hashtable that returns a mapping from cultures to ResourceSet objects.
(Inherited from ResourceManager.)
Top
Extension Methods

  NameDescription
Public Extension MethodConvert(Type, CultureInfo)Overloaded.
Converts an Object specified in the obj parameter to the desired targetType.
See the Examples section of the generic ConvertTTarget(Object, CultureInfo) overload for an example.
(Defined by ObjectExtensions.)
Public Extension MethodCode exampleConvertTTarget(CultureInfo)Overloaded.
Converts an Object specified in the obj parameter to the desired TTarget.
(Defined by ObjectExtensions.)
Public Extension MethodIn (Defined by ObjectExtensions.)
Public Extension MethodTryConvert(Type, Object)Overloaded.
Tries to convert an Object specified in the obj parameter to the desired targetType.
(Defined by ObjectExtensions.)
Public Extension MethodTryConvert(Type, CultureInfo, Object)Overloaded.
Tries to convert an Object specified in the obj parameter to the desired targetType.
(Defined by ObjectExtensions.)
Public Extension MethodTryConvertTTarget(TTarget)Overloaded.
Tries to convert an Object specified in the obj parameter to the desired TTarget.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example.
(Defined by ObjectExtensions.)
Public Extension MethodTryConvertTTarget(CultureInfo, TTarget)Overloaded.
Tries to convert an Object specified in the obj parameter to the desired TTarget.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example.
(Defined by ObjectExtensions.)
Top
Remarks

ResXResourceManager class is derived from ResourceManager so it can be used the same way. The main difference is that instead of working with binary compiled resources the ResXResourceManager class uses XML resources (.resx files) directly. As an IExpandoResourceManager implementation it is able to add/replace/remove entries in the resource sets belonging to specified cultures and it can save the changed contents.

See the Comparison with ResourceManager section to see all of the differences.

Tip Tip
To see when to use the ResXResourceReader, ResXResourceWriter, ResXResourceSet, ResXResourceManager, HybridResourceManager and DynamicResourceManager classes see the documentation of the KGySoft.Resources namespace.

Example: Using XML resources created by Visual Studio

You can create XML resource files by Visual Studio and you can use them by ResXResourceManager. See the following example for a step-by-step guide.

  1. Create a new project (Console Application)
    New console application
  2. In Solution Explorer right click on ConsoleApp1, Add, New Folder, name it Resources.
  3. In Solution Explorer right click on Resources, Add, New Item, Resources File.
    New Resources file
  4. In Solution Explorer right click on the new resource file (Resource1.resx if not named otherwise) and select Properties
  5. The default value of Build Action is Embedded Resource, which means that the resource will be compiled into the assembly and will be able to be read by the ResourceManager class. To be able to handle it by the ResXResourceManager we might want to deploy the .resx file with the application. To do so, select Copy if newer at Copy to Output directory. If we want to use purely the .resx file, then we can change the Build Action to None and we can clear the default Custom Tool value because we do not need the generated file.
    Resources1.resx properties
    Note Note
    To use both the compiled binary resources and the .resx file you can use the HybridResourceManager and DynamicResourceManager classes.
  6. Now we can either use the built-on resource editor of Visual Studio or just edit the .resx file by the XML Editor. If we add new or existing files to the resources, they will be automatically added to the project's Resources folder. Do not forget to set Copy if newer for the linked resources as well so they will be copied to the output directory along with the .resx file. Now add some string resources and files if you wish.
  7. To add culture-specific resources you can add further resource files with the same base name, extended by culture names. For example, if the invariant resource is called Resource1.resx, then a region neutral English resource can be called Resource1.en.resx and the American English resource can be called Resource1.en-US.resx.
  8. Reference KGySoft.CoreLibraries.dll and paste the following code in Program.cs:

C#
using System;
using System.Globalization;
using KGySoft;
using KGySoft.Resources;

public class Program
{
    public static void Main()
    {
        var enUS = CultureInfo.GetCultureInfo("en-US");
        var en = enUS.Parent;

        // The base name parameter is the name of the resource file without extension and culture specifier.
        // The ResXResourcesDir property denotes the relative path to the resource files.
        // Actually "Resources" is the default value.
        var resourceManager = new ResXResourceManager(baseName: "Resource1") { ResXResourcesDir = "Resources" };

        // Tries to get the resource from Resource1.en-US.resx, then Resource1.en.resx, then Resource1.resx
        // and writes the result to the console.
        Console.WriteLine(resourceManager.GetString("String1", enUS));

        // Sets the UI culture (similarly to Thread.CurrentThread.CurrentUICulture) so now this is the default
        // culture for looking up resources.
        LanguageSettings.DisplayLanguage = en;

        // The Current UI Culture is now en so tries to get the resource from Resource1.en.resx, then Resource1.resx
        // and writes the result to the console.
        Console.WriteLine(resourceManager.GetString("String1"));
    }
}

// A possible result of the example above (depending on the created resource files and the added content)
// 
// Test string in en-US resource set.
// Test string in en resource set.

Considering there are .resx files in the background not just String and other Object resources can be obtained by GetString and GetObject methods but metadata as well by GetMetaString and GetMetaObject methods. Please note that accessing aliases are not exposed by the ResXResourceManager class, but you can still access them via the IExpandoResourceSet type returned by the GetExpandoResourceSet method.

Note Note
Please note that unlike in case of GetString and GetObject methods, there is no falling back to the parent cultures (as seen in the example above) for metadata accessed by the GetMetaString and GetMetaObject methods.

Instantiating a ResXResourceManager object

You instantiate a ResXResourceManager object that retrieves resources from .resx files by calling one of its class constructor overloads. This tightly couples a ResXResourceManager object with a particular set of .resx files (see the previous example as well).

There are three possible constructors to use:

  • ResXResourceManager(baseName string, CultureInfo neutralResourcesLanguage = null) looks up resources in baseName.cultureName.resx files, where baseName.resx contains the resource set of the ultimate fallback culture (also known as default or invariant or neutral resources culture). If neutralResourcesLanguage is specified, then ResXResourceManager will use the baseName.resx file when the culture to be used equals to the neutralResourcesLanguage. If neutralResourcesLanguage is not specified, then the default culture is auto detected by the current application's NeutralResourcesLanguageAttribute. If it is not defined, then CultureInfo.InvariantCulture will be used as default culture.
    C#
    var manager = new ResXResourceManager("MyResources", CultureInfo.GetCultureInfo("en-US"));
  • ResXResourceManager(baseName string, Assembly assembly) is similar to the previous one, except that it does not set the default culture explicitly but tries to detect it from the provided Assembly. If it has a NeutralResourcesLanguageAttribute defined, then it will be used; otherwise, the CultureInfo.InvariantCulture will be used as the default culture.
    C#
    var manager = new ResXResourceManager("MyResources", typeof(Example).Assembly);
  • ResXResourceManager(Type resourceSource) will use the name of the provided Type as base name, and its Assembly to detect the default culture.
    C#
    var manager = new ResXResourceManager(typeof(Example));

Note Note
If a ResXResourceManager instance is created with a baseName without corresponding .resx file for the default culture, then accessing a non-existing resource will throw a MissingManifestResourceException unless ThrowException property is , in which case only a  value will be returned in such case. The exception can be avoided, if a resource set is created for the default culture either by adding a new resource (see next section) or by creating the resource set explicitly by calling the GetExpandoResourceSet method with CreateIfNotExists behavior.

Example: Adding and saving new resources at runtime

As ResXResourceManager maintains ResXResourceSet instances for each culture, it also supports adding new resources at runtime. By SetObject method you can add a resource to a specific culture. You can add metadata as well by SetMetaObject method. The resources and metadata can be removed, too (see RemoveObject and RemoveMetaObject methods).

The changes in the resource sets can be saved by calling the SaveAllResources method. A single resource set can be saved by calling the SaveResourceSet method.

Note Note
The ResXResourceManager always saves the resources into files and never embeds the resources if they are file references (see ResXFileRef). If you need more control over saving you can call the GetExpandoResourceSet method to access the various Save overloads)

C#
using System;
using System.Globalization;
using System.Resources;
using KGySoft;
using KGySoft.Resources;

// You can put this into AssemblyInfo.cs. Indicates that the invariant (default) resource set uses the American English culture.
// Try commenting out next line and see the differences.
[assembly:NeutralResourcesLanguage("en-US")]

public static class Example
{
    private static CultureInfo enUS = CultureInfo.GetCultureInfo("en-US");
    private static CultureInfo en = enUS.Parent;
    private static CultureInfo invariant = en.Parent;

    // Now that we don't specify the neutralResourcesLanguage optional parameter it will be auto detected
    private static ResXResourceManager manager = new ResXResourceManager("NewResource");

    public static void Main()
    {
        // If NewResource.resx does not exist yet a MissingManifestResourceException will be thrown here
        DumpValue("unknown");

        // This now creates the resource set for the default culture
        manager.SetObject("StringValue", "This is a string in the default resource", invariant);

        // No exception is thrown any more because the default resource set exists now.
        DumpValue("unknown");

        // If NeutralResourcesLanguage attribute above is active, invariant == enUS now. 
        manager.SetObject("StringValue", "This is a string in the English resource", en);
        manager.SetObject("StringValue", "This is a string in the American English resource", enUS);

        manager.SetObject("IntValue", 42, invariant);
        manager.SetObject("IntValue", 52, en);
        manager.SetObject("IntValue", 62, enUS);

        manager.SetObject("DefaultOnly", "This resource is the same everywhere", invariant);

        DumpValue("StringValue", invariant);
        DumpValue("StringValue", en);
        DumpValue("StringValue", enUS);

        DumpValue("IntValue", invariant);
        DumpValue("IntValue", en);
        DumpValue("IntValue", enUS);

        DumpValue("DefaultOnly", invariant);
        DumpValue("DefaultOnly", en);
        DumpValue("DefaultOnly", enUS);

        // This now creates NewResource.resx and NewResource.en.resx files
        manager.SaveAllResources(compatibleFormat: true); // so the saved files can be edited by VisualStudio
    }

    private static void DumpValue(string name, CultureInfo culture = null)
    {
        try
        {
            Console.WriteLine($"Value of resource '{name}' for culture '{culture ?? LanguageSettings.DisplayLanguage}': " +
                $"{manager.GetObject(name, culture) ?? "<null>"}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Accessing resource '{name}' caused an exception: {e.Message}");
        }
    }
}

// If NeutralLanguagesResource is en-US, the example above produces the following output:
// 
// Accessing resource 'unknown' caused an exception: Resource file not found: D:\ConsoleApp1\bin\Debug\Resources\NewResource.resx
// Value of resource 'unknown' for culture 'en-US': <null>
// Value of resource 'StringValue' for culture '': This is a string in the American English resource
// Value of resource 'StringValue' for culture 'en': This is a string in the English resource
// Value of resource 'StringValue' for culture 'en-US': This is a string in the American English resource
// Value of resource 'IntValue' for culture '': 62
// Value of resource 'IntValue' for culture 'en': 52
// Value of resource 'IntValue' for culture 'en-US': 62
// Value of resource 'DefaultOnly' for culture '': This resource is the same everywhere
// Value of resource 'DefaultOnly' for culture 'en': This resource is the same everywhere
// Value of resource 'DefaultOnly' for culture 'en-US': This resource is the same everywhere

Safety 

Similarly to ResXResourceSet and ResXResourceReader, the ResXResourceManager class also has a SafeMode which changes the behavior of GetString/GetMetaString and GetObject/GetMetaObject methods:

  • If the SafeMode property is  the return value of GetObject and GetMetaObject methods is a ResXDataNode rather than the resource or metadata value. This makes possible to check the raw .resx content before deserialization if the .resx file is from an untrusted source. The actual value can be obtained by the ResXDataNode.GetValue method. See also the third example at the ResXResourceSet class.
  • If the SafeMode property is , then GetString and GetMetaString methods will not throw an InvalidOperationException even for non-string entries; they return the raw XML value instead.
  • If the SafeMode property is , then GetStream and GetMetaStream methods will not throw an InvalidOperationException. For values, which are neither MemoryStream nor byte[] instances, they return a stream wrapper for the same string value that is returned by the GetString/GetMetaString methods.
Security note Security Note
Even if SafeMode is , loading a .resx content with corrupt or malicious entry will have no effect until we try to obtain the corresponding value. See the last example at ResXResourceSet for the demonstration and the example at ResXDataNode to see what members can be checked in safe mode.

Comparison with ResourceManager 

While ResourceManager is read-only and works on binary resources, ResXResourceManager supports expansion (see IExpandoResourceManager) and works on XML resource (.resx) files.

Incompatibility with ResourceManager:

  • There is no constructor where the type of the resource sets can be specified. The ResourceSetType property returns always the type of ResXResourceSet.
  • If ResourceManager.GetResourceSet method is called with createIfNotExists = false for a culture, which has a corresponding but not loaded resource file, then a resource set for a parent culture might be cached and on successive calls that cached parent set will be returned even if the createIfNotExists argument is . In ResXResourceManager the corresponding argument of the GetResourceSet method has been renamed to loadIfExists and works as expected.
  • The GetStream methods have MemoryStream return type instead of UnmanagedMemoryStream and they can be used also for byte[] values.

New features and improvements compared to ResourceManager:

  • Write support - The stored content can be expanded or existing entries can be replaced (see SetObject/SetMetaObject), the entries can be removed (see RemoveObject/RemoveMetaObject), and the new content can be saved (see SaveAllResources/SaveResourceSet). You can start even with a completely empty manager, add content dynamically and save the new resources (see the example above).
  • Security - During the initialization of ResXResourceManager and loading of a resource set no object is deserialized even if SafeMode property is . Objects are deserialized only when they are accessed (see GetObject/GetMetaObject). If SafeMode is , then security is even more increased because GetObject and GetMetaObject methods return a ResXDataNode instance instead of a deserialized object so you can check whether the resource or metadata can be treat as a safe object before actually deserializing it. See the Safety section above for more details.
  • Disposal - As ResourceSet implementations are disposable objects, ResXResourceManager itself implements the IDisposable interface as well.

See Also

Reference