ResXResourceManager Class

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.

Definition

Namespace: KGySoft.Resources
Assembly: KGySoft.CoreLibraries (in KGySoft.CoreLibraries.dll) Version: 9.0.0-preview.1
C#
[SerializableAttribute]
public class ResXResourceManager : ResourceManager, 
	IExpandoResourceManager, IDisposable
Inheritance
Object    ResourceManager    ResXResourceManager
Implements
IExpandoResourceManager, IDisposable

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.

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
  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

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:

  Note

If a ResXResourceManager instance is created with a baseName without a 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. 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 the SetObject method you can add a resource to a specific culture. You can add metadata as well by the 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

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:

  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.

Constructors

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

Properties

CloneValues Gets or sets whether GetObject and GetMetaObject methods return always a new copy of the stored values.
Default value: .
IgnoreResXParseErrors Gets or sets whether .resx file errors should be ignored when attempting to load a resource set. If , then non-loadable resource sets are considered as missing ones; otherwise, an exception is thrown.
Default value: .
IsDisposed Gets whether this ResXResourceManager instance is disposed.
IsModified Gets whether this ResXResourceManager instance has modified and unsaved data.
ResXResourcesDir Gets or sets the relative path to .resx resource files.
Default value: Resources
SafeMode Gets or sets whether the ResXResourceManager works in safe mode. In safe mode the retrieved objects are not deserialized automatically.
Default value: .
ThrowException Gets or sets whether a MissingManifestResourceException should be thrown when a resource .resx file is not found even for the neutral culture.
Default value: .

Methods

Dispose Disposes the resources of the current instance.
Dispose(Boolean) Releases the resources used by this ResXResourceManager instance.
GetExpandoResourceSet Retrieves the resource set for a particular culture, which can be dynamically modified.
GetMetaObject Returns the value of the specified non-string metadata for the specified culture.
GetMetaStream Returns a MemoryStream instance from the metadata of the specified name and culture.
GetMetaString Returns the value of the string metadata for the specified culture.
GetObject(String) Returns the value of the specified resource.
See the Remarks section of the ResXResourceManager class for examples.
(Overrides ResourceManagerGetObject(String))
GetObject(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))
GetResourceFileName Generates the name of the resource file for the given CultureInfo object.
(Overrides ResourceManagerGetResourceFileName(CultureInfo))
GetResourceSet Retrieves the resource set for a particular culture.
(Overrides ResourceManagerGetResourceSet(CultureInfo, Boolean, Boolean))
GetStream(String) Returns a MemoryStream instance from the resource of the specified name.
GetStream(String, CultureInfo) Returns a MemoryStream instance from the resource of the specified name and culture.
GetString(String) Returns the value of the specified string resource.
(Overrides ResourceManagerGetString(String))
GetString(String, CultureInfo) Returns the value of the string resource localized for the specified culture.
(Overrides ResourceManagerGetString(String, CultureInfo))
InternalGetResourceSet Provides the implementation for finding a resource set.
(Overrides ResourceManagerInternalGetResourceSet(CultureInfo, Boolean, Boolean))
ReleaseAllResources Disposes all of the cached ResXResourceSet instances and releases all resources.
(Overrides ResourceManagerReleaseAllResources)
RemoveMetaObject Removes a metadata object from the current ResXResourceManager with the specified name for the specified culture.
RemoveObject Removes a resource object from the current ResXResourceManager with the specified name for the specified culture.
SaveAllResources Saves all already loaded resources.
SaveResourceSet Saves the resource set of a particular culture if it has been already loaded.
SetMetaObject Adds or replaces a metadata object in the current ResXResourceManager with the specified name for the specified culture.
SetObject Adds or replaces a resource object in the current ResXResourceManager with the specified name for the specified culture.

Extension Methods

Convert 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)
ConvertTTarget Converts an Object specified in the obj parameter to the desired TTarget.
(Defined by ObjectExtensions)
In Gets whether item is among the elements of set.
See the Examples section of the generic InT(T, T) overload for an example.
(Defined by ObjectExtensions)
TryConvert Tries to convert an Object specified in the obj parameter to the desired targetType.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example.
(Defined by ObjectExtensions)
TryConvert Tries to convert an Object specified in the obj parameter to the desired targetType.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example.
(Defined by ObjectExtensions)
TryConvertTTarget 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)
TryConvertTTarget 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)

See Also