Структура DI создана для внедрения зависимостей, и локализация может быть просто одной из ваших услуг, поэтому в этом случае нет никакой причины , а не , использовать IMO структуры DI.Возможно, нам следует начать обсуждение предоставленного интерфейса 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();
}
}
}
Этот подход использует лучшее из обоих миров, потому что ключи не будут разбросаны по приложению, и добавление новых свойств просто должно быть сделано в одном месте.Используя вашу любимую библиотеку 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()));
Обратите внимание, что этот декоратор кэшируетстроковые ресурсы на неопределенный срок, что может привести к утечкам памяти, поэтому вы хотите обернуть строки в WeakReference
экземплярах или иметь какое-то время ожидания истечения.Но идея в том, что вы можете применять кеширование, не меняя существующую реализацию.
Надеюсь, это поможет.