建立自定义的数据驱动的本地化资源provider

  原文很长,为了便于阅读和理解,特将该文章改写成通俗易懂而且内容精炼的中文.

  预备知识:系统默认的处理资源和本地化的方法是使用resx文件存储资源.

  要使用自定义的resource provider,需要2个步骤:

  a) 修改web.config 文件,以便系统使用自定义的资源提供者

  b) 建立自定义资源提供者类,最少包括3个:

  1.ResourceProviderFactory,工厂类,用来建立ResourceProvider对象.

  2.ResourceProvider,实现IResourceProvider,IImplicitResourceProvider,IwwResourceProvider 接口.

  3.ResourceReader 实现IResourceReader.

  修改web.config 文件,以使用自定义的资源提供者。

  

复制代码 代码如下:

  <configuration>

  <system.web>

  <globalization resourceProviderFactoryType="Westwind.Globalization.DbSimpleResourceProviderFactory,Westwind.Globalization" />

  </system.web>

  </configuration>

  建立自定义资源提供者类:

  1.工厂类

  

复制代码 代码如下:

  [DesignTimeResourceProviderFactoryAttribute(typeof(DbDesignTimeResourceProviderFactory))]

  public class DbSimpleResourceProviderFactory : ResourceProviderFactory

  {

  public override IResourceProvider CreateGlobalResourceProvider(string classname)

  {

  return new DbSimpleResourceProvider(null, classname);

  }

  public override IResourceProvider CreateLocalResourceProvider(string virtualPath)

  {

  string ResourceSetName = DbResourceConfiguration.Current.StripVirtualPath(virtualPath);

  return new DbSimpleResourceProvider(null,ResourceSetName.ToLower());

  }

  }

  2.提供者类

  

复制代码 代码如下:

  public class DbSimpleResourceProvider : IResourceProvider, IImplicitResourceProvider

  {

  private string _ResourceSetName;

  private IDictionary _resourceCache;

  private DbSimpleResourceProvider()

  { }

  public DbSimpleResourceProvider(string virtualPath, string className)

  {

  _ResourceSetName = className;

  }

  private IDictionary GetResourceCache(string cultureName)

  {

  if (cultureName == null)

  cultureName = "";

  if (this._resourceCache == null)

  this._resourceCache = new ListDictionary();

  IDictionary Resources = this._resourceCache[cultureName] as IDictionary;

  if (Resources == null)

  {

  // *** DEPENDENCY HERE (#1): Using DbResourceDataManager to retrieve resources

  // *** Use datamanager to retrieve the resource keys from the database

  DbResourceDataManager Data = new DbResourceDataManager();

  Resources = Data.GetResourceSet(cultureName as string, this._ResourceSetName);

  this._resourceCache[cultureName] = Resources;

  }

  return Resources;

  }

  public void ClearResourceCache()

  {

  this._resourceCache.Clear();

  }

  object IResourceProvider.GetObject(string ResourceKey, CultureInfo Culture)

  {

  string CultureName = null;

  if (Culture != null)

  CultureName = Culture.Name;

  else

  CultureName = CultureInfo.CurrentUICulture.Name;

  return this.GetObjectInternal(ResourceKey, CultureName);

  }

  object GetObjectInternal(string ResourceKey, string CultureName)

  {

  IDictionary Resources = this.GetResourceCache(CultureName);

  object value = null;

  if (Resources == null)

  value = null;

  else

  value = Resources[ResourceKey];

  // *** If we're at a specific culture (en-Us) and there's no value fall back

  // *** to the generic culture (en)

  if (value == null && CultureName.Length > 3)

  {

  // *** try again with the 2 letter locale

  return GetObjectInternal(ResourceKey,CultureName.Substring(0,2) );

  }

  // *** If the value is still null get the invariant value

  if (value == null)

  {

  Resources = this.GetResourceCache("");

  if (Resources == null)

  value = null;

  else

  value = Resources[ResourceKey];

  }

  // *** If the value is still null and we're at the invariant culture

  // *** let's add a marker that the value is missing

  // *** this also allows the pre-compiler to work and never return null

  if (value == null && string.IsNullOrEmpty(CultureName))

  {

  // *** No entry there

  value = "";

  // *** DEPENDENCY HERE (#2): using DbResourceConfiguration and DbResourceDataManager to optionally

  // add missing resource keys

  // *** Add a key in the repository at least for the Invariant culture

  // *** Something's referencing but nothing's there

  if (DbResourceConfiguration.Current.AddMissingResources)

  new DbResourceDataManager().AddResource(ResourceKey, value.ToString(), "", this._ResourceSetName);

  }

  return value;

  }

  3.Reader类

  

复制代码 代码如下:

  public class DbSimpleResourceReader : IResourceReader

  {

  private IDictionary _resources;

  public DbSimpleResourceReader(IDictionary resources)

  {

  _resources = resources;

  }

  IDictionaryEnumerator IResourceReader.GetEnumerator()

  {

  return _resources.GetEnumerator();

  }

  void IResourceReader.Close()

  {

  }

  IEnumerator IEnumerable.GetEnumerator()

  {

  return _resources.GetEnumerator();

  }

  void IDisposable.Dispose()

  {

  }

  }

  完毕。

  本人没有测试过,待测试通过,献上最精炼的源代码.敬请稍候.