自定义资源读取器






2.81/5 (11投票s)
使用数据库实现自定义资源读取器

引言
本文将帮助您创建一个自定义资源读取器,如果您是新手。资源是应用程序构建的一个特性,允许您将特定于文化的内容放置在附属文件中,而不是直接放置在主应用程序中。 当您构建应用程序时,您可以识别出特定于文化的内容,并为每个您认为您的应用程序可能使用的文化创建一个不同的资源文件。 在运行时,将根据用户文化设置加载适当的资源集。 使用的特定设置是您的线程的 CurrentUICulture
,用户可以通过编程方式进行设置。
当您制作应用程序时,它会被放置在一个“程序集”中。一个程序集由以下部分组成
- 程序集元数据,也称为程序集清单
- 类型元数据
- 实现类型的 Microsoft 中间语言 (MSIL) 代码
- 一组资源
您也可以将这些资源文件放在外部存储库中,例如数据库。为此,您必须为您的应用程序创建一个自定义资源读取器。
Using the Code
对于本文,特定于语言的资源元素被放置在 Microsoft SQL Server 数据库中。创建一个 SQL Server 数据库,其中包含一个名为 Messages
的表。 它的 create
脚本如下所示
CREATE TABLE [dbo].[Messages]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Key] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Default] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[de] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[mn] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_Messages] PRIMARY KEY CLUSTERED ([Id] ASC)WITH _
(IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
创建自定义资源读取器有三个步骤。第一步是创建一个实现 IResourceReader
的类,它需要一个 Close
方法和一个 GetEnumerator
的实现。
public class DBResourceReader:IResourceReader
{
//Database Connection
private string ConnectionString;
//Language to retrieve
private string Language;
//Constructor
public DBResourceReader(string ConnectionString, CultureInfo Culture)
{
this.ConnectionString = ConnectionString;
this.Language = Culture.Name;
}
//To get enumerator to iterate through the resources hashtable
public IDictionaryEnumerator GetEnumerator()
{
//Hashtable to store Key-values pairs for resources
Hashtable htLanguage = new Hashtable();
//SQL DB connection to database
SqlConnection conn = new SqlConnection(ConnectionString);
//Command to select specific language key value
SqlCommand command = conn.CreateCommand();
if (Language == "")
Language = "Default";
command.CommandText = "Select [key], [" + Language + "] from Messages";
try
{
conn.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
//Add all the key value pairs for specific language to a hashtable
if (reader.GetValue(1) != System.DBNull.Value)
htLanguage.Add(reader.GetString(0), reader.GetString(1));
}
reader.Close();
}
catch {}
finally
{
conn.Close();
}
return htLanguage.GetEnumerator();
}
//You may close db connection here.
public void Close()
{ }
//dispose resources that are not required
public void Dispose()
{ }
//Implement IEnumerable interface
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
下一步是生成一个自定义资源集。它存储为一种特定文化本地化的所有资源。 为此,创建 DBResourceSet
的派生类,并重写 GetDefaultReader
public class DBResourceSet:ResourceSet
{
public DBResourceSet(string ConnectionString, CultureInfo Culture):
base(new DBResourceReader(ConnectionString,Culture))
{}
//Return custom reader as default one for reading language resources
public override Type GetDefaultReader()
{
return typeof(DBResourceReader);
}
}
下一步是生成一个使用自定义读取器的自定义资源管理器。 为此,创建一个 ResourceManager
的派生类,并重写 InternalGetResourceSet
以允许创建前面定义的资源读取器。 以下代码示例演示了一个简单的 ResourceManager
public class DBResourceManager : ResourceManager
{
//Connection string for database
private string ConnectionString;
//Constructor
public DBResourceManager(string ConnectionString)
{
this.ConnectionString = ConnectionString;
//initialize ResourceSets hashtable
ResourceSets = new Hashtable();
}
//ResourceManager.GetString() makes use of this function
protected override ResourceSet InternalGetResourceSet(
CultureInfo culture, bool createIfNotExists, bool tryParents)
{
DBResourceSet rs = null;
if (ResourceSets.Contains(culture.Name))
{
rs = (DBResourceSet)ResourceSets[culture.Name];
}
else
{
rs = new DBResourceSet(ConnectionString, culture);
ResourceSets.Add(culture.Name, rs);
}
return rs;
}
}
结论
本文介绍了如何通过使用 SQL Server 数据库作为资源存储库来存储本地化资源,从而创建一个自定义资源读取器。您也可以通过使用不同的资源存储库来实现资源读取器接口。