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

时间:2021-10-04 14:25:25

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

预备知识:系统默认的处理资源和本地化的方法是使用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() 



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