65.9K
CodeProject 正在变化。 阅读更多。
Home

自定义资源读取器

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.81/5 (11投票s)

2006年5月17日

CPOL

2分钟阅读

viewsIcon

56145

downloadIcon

1268

使用数据库实现自定义资源读取器

Sample Image - Custom_Resource_Reader.jpg

引言

本文将帮助您创建一个自定义资源读取器,如果您是新手。资源是应用程序构建的一个特性,允许您将特定于文化的内容放置在附属文件中,而不是直接放置在主应用程序中。 当您构建应用程序时,您可以识别出特定于文化的内容,并为每个您认为您的应用程序可能使用的文化创建一个不同的资源文件。 在运行时,将根据用户文化设置加载适当的资源集。 使用的特定设置是您的线程的 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 数据库作为资源存储库来存储本地化资源,从而创建一个自定义资源读取器。您也可以通过使用不同的资源存储库来实现资源读取器接口。

© . All rights reserved.