With the resource readers that are part of .NET Framework 3.5, you can read resources from resburce tiles and satellite assemblies. If you want to put the resources into a different store (such as a database), you can use a custom resource reader to read these resources.
To use a custom resource reader, you also need to create a custom resource set and a custom esource manager. Doing this is not a difficult task, however, because you can derive the custom classes from
For the sample application, yeu need to create a simple database with just one table for storing messages that has one column for every supported language. The following table lists the columns and their corresponding values.
For the custom resource reader, you create a component library with three classes. The classes are DatabaseResourceReader, DatabaseResourceSet, and Database ResourceManager.
Creating a Database Resource Reader
With the “klss DatabaseResourceReader, you define two fields: the connection string that is needed to access the database and the language that should be returned by the reader. These fields are filled inside the constructor of this class. The field language is set to the name of the culture that is passed with the CuI turelnfo object to the constructor:
A resource reader has to implement the interface IResourceReader. This interface defines the methods Close () and GetEnumerator () to return an IDictionaryEnumerator that returns keys and values for the resources. In the implementation of GetEnumerator (), create a Hashtable where all keys and value; for a ~?~if;c ‘anguage are stored. Next, you can use the SqlConnection class in the namespace System. o.ta SqlClient to access the database in SQL Server. Connection. CreateComrnand ( ) creates a Sq!Comrnand () object .hat you use to specify the SQL SELECTstatement to access the data in he database. If th, language is set to de, the SELECT statement is SELECT [key], [de] FROM ·Messages. Then you use a SqlDataReader object to read all values from the database, and put it into a asrtable. Finally, the enumerator of the Hashtable is returned.
For more information about ••ccessing data with ADO.NET, see Chapter 26, “Data Access.”
Because the interface IResourceReader is derived from IEnumerable and IDisposable, the methods GetEnumerator (),which returns an IEnumerator interface, and Dispose () must be implemented, too:
Cleating a’ DatabaseResoulceSet
The class DatabaseResourceSet can use nearly all implementations of the base class ResourceSet. You just need a different constructor that initializes the base class with your own resource reader, DatabaseResourceReader. The constructor of ResourceSet allows passing an object by implementing
IResourceReader; this requirement is fulfilled by DatabaseResourceReader:
Creating a Database Resource Manager
The third class you have to create is the custom resource manager. DatabaseResourceManager is derived from the class ResourceManager, and you only have to implement a new constructor and override the method InternalGetResourceSet ( ) . In the constructor, create a new Hashtable to store all queried resource sets and set it into the field ResourceSets defined by the base class: public class DatabaseResourceManager ResourceManager
The methods of the ResourceManager class that you can use to access resources (such as GetString ( ) and GetObj eet ( ) ) invoke the method InternalGetResourceSet () to access a resource set where the appropriate values can be returned. In the implementation of InternalGetResourceSet (), check first if the resource set for the culture queried for a resource is already in the hash table; if it already exists, return it to the caller. If the resource
set is not available, create a new DatabaseResourceSet object with the queried culture, add it to the hash table, and .return it to the caller: