KGy SOFT

ResXResourceReader Class

KGy SOFT Core Libraries Help
Enumerates XML resource (.resx) files and streams, and reads the sequential resource name and value pairs.
See the Remarks section for examples and for the differences compared to System.Resources.ResXResourceReader class.
Inheritance Hierarchy

SystemObject
  KGySoft.ResourcesResXResourceReader

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

public sealed class ResXResourceReader : IResourceReader, 
	IEnumerable, IDisposable

The ResXResourceReader type exposes the following members.

Constructors

  NameDescription
Public methodResXResourceReader(Stream, ITypeResolutionService)
Initializes a new instance of the ResXResourceReader class for the specified stream.
Public methodResXResourceReader(TextReader, ITypeResolutionService)
Initializes a new instance of the ResXResourceReader class for the specified TextReader.
Public methodResXResourceReader(String, ITypeResolutionService)
Initializes a new instance of the ResXResourceReader class for the specified resource file.
Top
Properties

  NameDescription
Public propertyAllowDuplicatedKeys
Gets or sets whether all entries of same name of the .resx file should be returned.
Default value: .
Public propertyBasePath
Gets or sets the base path for the relative file path specified in a ResXFileRef object.
Default value: .
Public propertyCheckHeader
Gets or sets whether "resheader" entries are checked in the .resx file. When , a NotSupportedException can be thrown during the enumeration when "resheader" entries contain invalid values. When header entries are missing, no exception is thrown.
Default value: .
Public propertySafeMode
Gets or sets whether ResXDataNode objects are returned when reading the current XML resource file or stream.
Public propertyUseResXDataNodes Obsolete.
Gets or sets whether ResXDataNode objects are returned when reading the current XML resource file or stream.
Top
Methods

  NameDescription
Public methodClose
Releases all resources used by the ResXResourceReader.
Public methodEquals
Determines whether the specified object is equal to the current object.
(Inherited from Object.)
Protected methodFinalize
This member overrides the Finalize method.
(Overrides ObjectFinalize.)
Public methodStatic memberFromFileContents
Creates a new ResXResourceReader object and initializes it to read a string whose contents are in the form of an XML resource file.
Public methodGetAliasEnumerator
Provides an IDictionaryEnumerator instance that can retrieve the aliases from the current XML resource file or stream.
Public methodGetEnumerator
Returns an IDictionaryEnumerator instance for the current ResXResourceReader object that enumerates the resources in the source XML resource file or stream.
Public methodGetHashCode
Serves as the default hash function.
(Inherited from Object.)
Public methodGetMetadataEnumerator
Returns an IDictionaryEnumerator instance for the current ResXResourceReader object that enumerates the design-time properties (<metadata> elements) in the source XML resource file or stream.
Public methodGetType
Gets the Type of the current instance.
(Inherited from Object.)
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
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 MethodIndexOf(FuncObject, Boolean)Overloaded.
Searches for an element in the source enumeration where the specified predicate returns .
(Defined by EnumerableExtensions.)
Public Extension MethodIndexOf(Object)Overloaded.
Searches for an element in the source enumeration.
(Defined by EnumerableExtensions.)
Public Extension MethodIsNullOrEmpty
Determines whether the specified source is  or empty (has no elements).
(Defined by EnumerableExtensions.)
Public Extension MethodTryAdd
Tries to add the specified item to the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryAddRange
Tries to add the specified collection to the target collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryClear
Tries to remove all elements from the collection.
(Defined by EnumerableExtensions.)
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.)
Public Extension MethodTryGetElementAt
Tries to get an item at the specified index in the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryInsert
Tries to insert the specified item at the specified index to the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryInsertRange
Tries to insert the specified collection into the target collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryRemove
Tries to remove the specified item from to the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryRemoveAt
Tries to remove an item at the specified index from the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryRemoveRange
Tries to remove count amount of items from the specified collection at the specified index.
(Defined by EnumerableExtensions.)
Public Extension MethodTryReplaceRange
Tries to remove count amount of items from the target at the specified index, and to insert the specified collection at the same position. The number of elements in collection can be different from the amount of removed items.
(Defined by EnumerableExtensions.)
Public Extension MethodTrySetElementAt
Tries to set the specified item at the specified index in the collection.
(Defined by EnumerableExtensions.)
Top
Remarks

Note Note
This class is similar to System.Resources.ResXResourceReader in System.Windows.Forms.dll. See the Comparison with System.Resources.ResXResourceReader section for 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.

You can use the ResXResourceReader class to enumerate resources in .resx files by traversing the dictionary enumerator (IDictionaryEnumerator) that is returned by the GetEnumerator method. You call the methods provided by IDictionaryEnumerator to advance to the next resource and to read the name and value of each resource in the .resx file.

Note Note
The ResXResourceReader class provides more enumerators.
  • The GetEnumerator method returns an IDictionaryEnumerator object, which enumerates the resources. The IDictionaryEnumerator.Key property returns the resource names, while IDictionaryEnumerator.Value returns either ResXDataNode instances, if SafeMode property is ; or returns deserialized Object instances if SafeMode property is .
  • The GetMetadataEnumerator method returns an IDictionaryEnumerator object, which enumerates the metadata entries. The IDictionaryEnumerator.Key property returns the metadata names, while IDictionaryEnumerator.Value returns either ResXDataNode instances, if SafeMode property is ; or returns deserialized Object instances if SafeMode property is .
  • The GetAliasEnumerator method returns an IDictionaryEnumerator object, which enumerates the aliases in the .resx file. The IDictionaryEnumerator.Key property returns the alias names, while IDictionaryEnumerator.Value returns the corresponding assembly names for the alias names.
  • As an explicit interface implementation, ResXResourceReader implements IEnumerable.GetEnumerator method, which returns the same enumerator as the GetEnumerator method as an IEnumerator instance. The IEnumerator.Current property will return DictionaryEntry instances.

If the SafeMode property is , the value of the IDictionaryEnumerator.Value property is a ResXDataNode instance rather than the resource value. This makes possible to check the raw .resx content before deserialization if the .resx file is from an untrusted source. See also the example at ResXDataNode.

If you want to retrieve named resources from a .resx file rather than enumerating its resources, then you can instantiate a ResXResourceSet object and call its GetString/GetObject, GetMetaString/GetMetaObject and GetAliasValue methods. Also ResXResourceSet supports SafeMode.

Examples

The following example shows how to enumerate the resources, metadata and aliases of a .resx file and what is the difference between safe and non-safe mode. Please note that SafeMode property can be switched on and off during the enumeration, too. Please also note that the values returned by the GetAliasEnumerator are always strings, regardless of the value of SafeMode property. See also the example of the ResXDataNode class to see how to examine the properties of the ResXDataNode instances in safe mode.
C#
 using System;
 using System.Collections;
 using System.IO;
 using KGySoft.Resources;

 public class Example
 {
     private const string resx = @"<?xml version='1.0' encoding='utf-8'?>
 <root>
   <data name='string'>
     <value>Test string</value>
     <comment>Default data type is string.</comment>
   </data>

   <metadata name='meta string'>
     <value>Meta String</value>
   </metadata>

   <data name='int' type='System.Int32'>
     <value>42</value>
   </data>

   <assembly alias='CustomAlias' name='System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' />

   <data name='color' type='System.Drawing.Color, CustomAlias'>
     <value>Red</value>
     <comment>When this entry is deserialized, System.Drawing assembly will be loaded.</comment>
   </data>

   <data name='bytes' type='System.Byte[]'>
     <value>VGVzdCBieXRlcw==</value>
   </data>

   <data name='dangerous' mimetype='application/x-microsoft.net.object.binary.base64'>
     <value>YmluYXJ5</value>
     <comment>BinaryFormatter will throw an exception for this invalid content.</comment>
   </data>

 </root>";

    public static void Main()
    {
        var reader = new ResXResourceReader(new StringReader(resx));
        Console.WriteLine("____Resources in .resx:____");
        Dump(reader, reader.GetEnumerator);
        Console.WriteLine("____Metadata in .resx:____");
        Dump(reader, reader.GetMetadataEnumerator);
        Console.WriteLine("____Aliases in .resx:____");
        Dump(reader, reader.GetAliasEnumerator);
    }

    private static void Dump(ResXResourceReader reader, Func<IDictionaryEnumerator> getEnumeratorFunction)
    {
        var enumerator = getEnumeratorFunction();
        while (enumerator.MoveNext())
        {
            Console.WriteLine($"Name: {enumerator.Key}");
            reader.SafeMode = true;
            Console.WriteLine($"  Value in SafeMode:     {enumerator.Value} ({enumerator.Value.GetType()})");
            try
            {
                reader.SafeMode = false;
                Console.WriteLine($"  Value in non-SafeMode: {enumerator.Value} ({enumerator.Value.GetType()})");
            }
            catch (Exception e)
            {
                Console.WriteLine($"Getting the deserialized value thrown an exception: {e.Message}");
            }
            Console.WriteLine();
        }
    }
}

 // The example displays the following output:
 // ____Resources in .resx:____
 // Name: string
 // Value in SafeMode:     Test string (KGySoft.Resources.ResXDataNode)
 // Value in non-SafeMode: Test string (System.String)

 // Name: int
 // Value in SafeMode:     42 (KGySoft.Resources.ResXDataNode)
 // Value in non-SafeMode: 42 (System.Int32)

 // Name: color
 // Value in SafeMode:     Red (KGySoft.Resources.ResXDataNode)
 // Value in non-SafeMode: Color[Red] (System.Drawing.Color)

 // Name: bytes
 // Value in SafeMode:     VGVzdCBieXRlcw== (KGySoft.Resources.ResXDataNode)
 // Value in non-SafeMode: System.Byte[] (System.Byte[])

 // Name: dangerous
 // Value in SafeMode:     YmluYXJ5 (KGySoft.Resources.ResXDataNode)
 // Getting the deserialized value thrown an exception: End of Stream encountered before parsing was completed.

 // ____Metadata in .resx:____
 // Name: meta string
 // Value in SafeMode:     Meta String (KGySoft.Resources.ResXDataNode)
 // Value in non-SafeMode: Meta String (System.String)

 // ____Aliases in .resx:____
 // Name: CustomAlias
 // Value in SafeMode:     System.Drawing, Version= 4.0.0.0, Culture= neutral, PublicKeyToken= b03f5f7f11d50a3a (System.String)
 // Value in non-SafeMode: System.Drawing, Version= 4.0.0.0, Culture= neutral, PublicKeyToken= b03f5f7f11d50a3a (System.String)

By default, ResXResourceReader allows duplicated keys with different values (see AllowDuplicatedKeys property). Though such a .resx file is not strictly valid, its complete content can be retrieved. When AllowDuplicatedKeys is , GetEnumerator, GetMetadataEnumerator and GetAliasEnumerator return a lazy enumerator for the first time meaning the .resx file is parsed only during the enumeration. When any of the enumerators are obtained for the second time, a cached enumerator is returned with the whole parsed .resx content. If duplicates are disabled, the lastly defined values will be returned of a redefined name. This behavior is similar to the System.Resources.ResXResourceReader class, which does not allow duplicates.

Examples

The following example demonstrates the difference of lazy (allowing duplicates) and greedy (disabling duplicates) reading.
C#
using System;
using System.Collections;
using System.IO;
using KGySoft.Resources;

public class Example
{
    private const string resx = @"<?xml version='1.0' encoding='utf-8'?>
<root>
  <data name='item'>
    <value>Test string</value>
  </data>

  <data name='item'>
    <value>This is a duplicate for key 'item'.</value>
  </data>
</root>";

    public static void Main()
    {
        // Allowing duplicates and lazy reading.
        Console.WriteLine("-------Lazy reading------");
        var reader = new ResXResourceReader(new StringReader(resx)) { AllowDuplicatedKeys = true };
        IDictionaryEnumerator enumerator = reader.GetEnumerator();
        Dump(enumerator); // if resx contains a syntax error, an exception is thrown during the enumeration.

        // Disabling duplicates and lazy reading
        Console.WriteLine("-------Greedy reading------");
        reader = new ResXResourceReader(new StringReader(resx)) { AllowDuplicatedKeys = false };
        enumerator = reader.GetEnumerator(); // if resx contains a syntax error, an exception is thrown here.
        Dump(enumerator);
    }

    private static void Dump(IDictionaryEnumerator enumerator)
    {
        while (enumerator.MoveNext())
        {
            Console.WriteLine($"Key: {enumerator.Key}");
            Console.WriteLine($"Value: {enumerator.Value}");
            Console.WriteLine();
        }
    }
}

// The example displays the following output:
// -------Lazy reading------
// Key: item
// Value: Test string
// 
// Key: item
// Value: This is a duplicate for key 'item'.
// 
// -------Greedy reading------
// Key: item
// Value: This is a duplicate for key 'item'.

Comparison with System.Resources.ResXResourceReader 

ResXResourceReader can read .resx files produced both by ResXResourceWriter and System.Resources.ResXResourceWriter.

Note Note
When reading a .resx file written by the System.Resources.ResXResourceWriter class, the System.Windows.Forms.dll is not loaded during resolving System.Resources.ResXFileRef and System.Resources.ResXNullRef types.

Incompatibility with System.Resources.ResXResourceReader:

  • Constructors do not have overloads with AssemblyName[] parameters. The System.Resources.ResXResourceReader uses them to load the assemblies in advance occasionally by calling the obsolete Assembly.LoadPartial method. However, this ResXResourceReader implementation can handle finding and loading assemblies automatically. If an assembly needs to be loaded from a partial name, the Reflector.ResolveAssembly method is called, which does not use obsolete techniques. If you need a completely custom type resolution the constructor overloads with ITypeResolutionService parameters still can be used.
  • This ResXResourceReader is a sealed class.
  • After disposing the ResXResourceReader instance or calling the Close method the enumerators cannot be obtained: an ObjectDisposedException will be thrown on calling GetEnumerator, GetMetadataEnumerator and GetAliasEnumerator methods.
  • After disposing the ResXResourceReader instance or calling the Close method every source stream will be closed (if any).
  • Unlike System.Resources.ResXResourceReader, this implementation returns every resources and metadata of the same name by default. This behavior can be adjusted by AllowDuplicatedKeys property.
  • System.Resources.ResXResourceReader often throws ArgumentException on getting the enumerator or on retrieving the value of a ResXDataNode instance, which contains invalid data. In contrast, this implementation may throw XmlException, TypeLoadException or NotSupportedException instead.
  • Though the UseResXDataNodes property is still supported, it is obsolete in favor of SafeMode property.
  • In System.Resources.ResXResourceReader if UseResXDataNodes property is , the resource and metadata entries are mixed in the returned enumerator, while when it is , then only the resources are returned. In this implementation the GetEnumerator always returns only the resources and GetMetadataEnumerator returns the metadata regardless of the value of the UseResXDataNodes and SafeMode properties.

New features and improvements compared to System.Resources.ResXResourceReader:

  • Lazy processing - If AllowDuplicatedKeys is , the .resx file is processed on demand, during the actual enumeration. The .resx file is processed immediately if AllowDuplicatedKeys is . If AllowDuplicatedKeys is  and any enumerator is obtained after getting one, the rest of the .resx file is immediately processed.
  • Handling duplicates - If AllowDuplicatedKeys is , every occurrence of a duplicated name is returned by the enumerators. Otherwise, only the last occurrence of a name is returned.
  • Headers - The .resx header is allowed to be completely missing; however, it is checked when exists and CheckHeader property is . If header tags contain invalid values a NotSupportedException may be thrown during the enumeration. You can configure the ResXResourceWriter class to omit the header by the ResXResourceWriter.OmitHeader property.
  • Using ResXDataNode instances - The SafeMode (UseResXDataNodes) property can be toggled also after getting an enumerator or even during the enumeration.
  • Clear purpose of the enumerators - The System.Resources.ResXResourceReader.GetEnumerator either returns resources only or returns both resources and metadata mixed together depending on the value of the System.Resources.ResXResourceReader.UseResXDataNodes property. This ResXResourceReader implementation has separated GetEnumerator, GetMetadataEnumerator and GetAliasEnumerator methods, which return always the resources, metadata and aliases, respectively.
  • Security - If SafeMode is , no deserialization, assembly loading and type resolving occurs until a deserialization is explicitly requested by calling the ResXDataNode.GetValue method on the IDictionaryEnumerator.Value instances returned by the GetEnumerator and GetMetadataEnumerator methods.
  • Base path - The BasePath property, which is used for resolving file references can be set during the enumeration, too.
  • New MIME type - A new MIME type text/kgysoft.net/object.binary.base64 is supported, indicating that an object is serialized by BinarySerializationFormatter instead of BinaryFormatter. The ResXResourceWriter can produce such .resx content if ResXResourceWriter.CompatibleFormat is .
  • Soap formatter support - The Soap formatter support is provided without referencing the System.Runtime.Serialization.Formatters.Soap.dll assembly. If the assembly cannot be loaded from the GAC (platform dependent), then a NotSupportedException will be thrown.
  • Type resolving - If an ITypeResolutionService instance is passed to one of the constructors, it is used also for the type references in ResXFileRef instances.

See Also

Reference