Ein DI-Framework ist gebaut, um Abhängigkeitsinjektion und Lokalisierung zu tun könnte nur einer Ihrer Dienste sein, so dass in diesem Fall gibt es keinen Grund nicht ein DI-Framework IMO zu verwenden. Vielleicht sollten wir anfangen, die bereitgestellte ILocalResources
Schnittstelle zu diskutieren. Obwohl ich der Kompilierzeit-Support bin, bin ich nicht sicher, ob die mitgelieferte Schnittstelle Ihnen helfen wird, da diese Schnittstelle wahrscheinlich der Typ in Ihrem System sein wird, der sich am meisten ändert. Und mit dieser Schnittstelle die Art/Typen, die es implementieren. Vielleicht sollten Sie mit einem anderen Design gehen.
Wenn wir uns die meisten Lokalisierungsframeworks/Provider/Factories (oder was auch immer) anschauen, sind sie alle stringbasiert. Aus diesem Grund, denken Sie an die folgende Konstruktion:
public interface ILocalResources
{
string GetStringResource(string key);
string GetStringResource(string key, CultureInfo culture);
}
Dies würde erlauben Sie Schlüssel und Kulturen auf die zugrunde liegende Nachrichtendatenspeicher hinzuzufügen, ohne die Schnittstelle zu ändern. Nachteil ist natürlich, dass Sie niemals einen Schlüssel ändern sollten, denn das wird wohl eine Hölle sein.
Ein weiterer Ansatz könnte eine abstrakte Basistyp sein:
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;
}
}
und Implementierung dieser Art könnte wie folgt aussehen:
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();
}
}
}
Dieser Ansatz Beste aus beiden Welten nimmt, da die Schlüssel gewonnen‘ t durch die Anwendung verstreut werden und neue Eigenschaften hinzugefügt werden, muss nur an einem einzigen Ort erfolgen. Verwenden Sie Ihre favorite DI Bibliothek können Sie eine Implementierung wie folgt registrieren:
container.RegisterSingleton<LocalResources>(new SqlLocalResources());
Und da die LocalResources
Typ genau eine abstrakte Methode, die die ganze Arbeit tut, ist es einfach, ein Dekorateur zu erstellen, die Caching anfordernden fügt zu verhindern die gleichen Daten aus der Datenbank:
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;
}
}
Sie den Dekorateur anwenden können wie folgt:
container.RegisterSingleton<LocalResources>(
new CachedLocalResources(new SqlLocalResources()));
Do not e dass dieser Decorator die String-Ressourcen unbegrenzt zwischenspeichert, was zu Speicherlecks führen kann. Daher möchten Sie die Strings in WeakReference
Instanzen verpacken oder eine Art Ablaufzeitlimit dafür haben. Die Idee ist jedoch, dass Sie Caching anwenden können, ohne eine vorhandene Implementierung ändern zu müssen.
Ich hoffe, das hilft.
Alternativ können Sie auch Erweiterungsmethoden für die 'ILocalResources' Schnittstelle, aber das abwärts gerichtete ist implementieren, dass Sie Methoden anstelle von Eigenschaften haben. Aber das wäre wahrscheinlich nicht so schlimm. – Steven