一個DI框架是爲依賴注入而構建的,本地化可能只是您的服務之一,所以在這種情況下,沒有理由使用DI框架IMO來執行而不是。也許我們應該開始討論提供的ILocalResources
接口。儘管我支持編譯時支持,但我不確定提供的接口是否會對您有所幫助,因爲該接口可能是您的系統中將改變最多的類型。並用該接口實現它的類型。也許你應該採用不同的設計。
當我們看看大多數本地化框架/供應商/工廠(或其他),他們是基於所有的字符串。因此,請考慮以下設計:
public interface ILocalResources
{
string GetStringResource(string key);
string GetStringResource(string key, CultureInfo culture);
}
這將允許您將密鑰和文化添加到基礎消息數據存儲,而不更改接口。當然,下滑當然不應該改變一個關鍵,因爲那可能是一個地獄。
另一種方法可能是一個抽象基類:
public abstract class LocalResources
{
public string OkMessage { get { return this.GetString("OK"); } }
public string CancelMessage { get { return this.GetString("Cancel"); } }
...
protected abstract string GetStringResource(string key,
CultureInfo culture);
private string GetString(string key)
{
Culture culture = CultureInfo.CurrentCulture;
string resource = GetStringResource(key, culture);
// When the resource is not found, fall back to the neutral culture.
while (resource == null && culture != CultureInfo.InvariantCulture)
{
culture = culture.Parent;
resource = this.GetStringResource(key, culture);
}
if (resource == null) throw new KeyNotFoundException(key);
return resource;
}
}
而實現這種類型的看起來是這樣的:
public sealed class SqlLocalResources : LocalResources
{
protected override string GetStringResource(string key,
CultureInfo culture)
{
using (var db = new LocalResourcesContext())
{
return (
from resource in db.StringResources
where resource.Culture == culture.Name
where resource.Key == key
select resource.Value).FirstOrDefault();
}
}
}
此方法採用兩全其美的,因爲鑰匙贏得」通過應用程序分散,並添加新的屬性只需要在一個地方完成。使用您favorite DI庫,你可以註冊一個這樣的實現:
container.RegisterSingleton<LocalResources>(new SqlLocalResources());
而且由於LocalResources
型有且只有一個,做所有的工作抽象方法,很容易創建一個裝飾,增加了緩存,從而避免請求
public sealed class CachedLocalResources : LocalResources
{
private readonly Dictionary<CultureInfo, Dictionary<string, string>> cache =
new Dictionary<CultureInfo, Dictionary<string, string>>();
private readonly LocalResources decoratee;
public CachedLocalResources(LocalResources decoratee) { this.decoratee = decoratee; }
protected override string GetStringResource(string key, CultureInfo culture) {
lock (this.cache) {
string res;
var cultureCache = this.GetCultureCache(culture);
if (!cultureCache.TryGetValue(key, out res)) {
cultureCache[key] = res= this.decoratee.GetStringResource(key, culture);
}
return res;
}
}
private Dictionary<string, string> GetCultureCache(CultureInfo culture) {
Dictionary<string, string> cultureCache;
if (!this.cache.TryGetValue(culture, out cultureCache)) {
this.cache[culture] = cultureCache = new Dictionary<string, string>();
}
return cultureCache;
}
}
您可以將裝飾如下:從數據庫中相同的數據
container.RegisterSingleton<LocalResources>(
new CachedLocalResources(new SqlLocalResources()));
不要e這個裝飾器會無限期地緩存字符串資源,這可能會導致內存泄漏,所以你希望包裝WeakReference
實例中的字符串,或者在它上面有某種過期超時。但想法是,您可以應用緩存而無需更改任何現有的實現。
我希望這會有所幫助。
另外,你也可以實現`ILocalResources`接口的擴展方法,但缺點是你將有方法而不是屬性。但那不會那麼糟糕。 – Steven 2011-01-10 15:48:07