2017-02-23 2 views
3

Ich habe eine IAppSettingsLoader Schnittstelle, die die Datei IO abstrahiert zum Laden meiner app.config Datei.Registrieren von Dekoratoren mit primitiven Konfigurationsabhängigkeiten in Simple Injector

public interface IAppSettingsLoader 
{ 
    IEnumerable<KeyValuePair<string, string>> LoadAppSettings(); 
} 

Ich habe eine Klasse, die die tatsächliche Datei lädt:

public class FileAppSettignsLoader : IAppSettingsLoader 
{ 
    public IEnumerable<KeyValuePair<string, string>> LoadAppSettings() 
    { 
     // Perform actual loading through ConfigurationManager.AppSettings 
    } 
} 

Dann habe ich einen Caching-Dekorateur, die Datei Änderungen an app.config

public class CachedAppSettingsLoader : IAppSettingsLoader 
{ 
    private readonly ObjectCache _cache; 
    private readonly string _cacheKey; 
    private readonly CacheItemPolicy _cacheItemPolicy; 
    private readonly IAppSettingsLoader _innerAppSettingsLoader; 

    public CachedAppSettingsLoader(ObjectCache cache, 
            string cacheKey, 
            CacheItemPolicy cacheItemPolicy, 
            IAppSettingsLoader innerAppSettingsLoader) 
    { 
     _cacheKey = cacheKey; 
     _cacheItemPolicy = cacheItemPolicy; 
     _cache = cache; 
     _innerAppSettingsLoader = innerAppSettingsLoader; 
    } 

    public IEnumerable<KeyValuePair<string, string>> LoadAppSettings() 
    { 
     object cached = _cache[_cacheKey]; 
     if (cached != null) 
     { 
      return (IEnumerable<KeyValuePair<string, string>>)cached; 
     } 

     var keyValuePairs = _innerAppSettingsLoader.LoadAppSettings(); 

     // _cacheItemPolicy will contain a HostFileChangeMonitor 
     _cache.Add(_cacheKey, keyValuePairs, _cacheItemPolicy); 
     return keyValuePairs; 
    } 
} 

Ich habe versucht, zu überwachen versucht zu registrieren dieser Caching Dekorateur mit Simple Injector ohne Erfolg. Das ist, was ich versuchte:

private void RegisterDependencies(Container container) 
{ 
    container.RegisterSingleton(() => 
     ResolveCachedAppSettingsLoader(container)); 
    container.Register<IAppSettingsLoader, FileAppSettingsLoader>(
     Lifestyle.Singleton); 
    container.RegisterDecorator<IAppSettingsLoader, CachedAppSettingsLoader>(
     Lifestyle.Singleton); 
} 

private CachedAppSettingsLoader ResolveCachedAppSettingsLoader(Container container) 
{ 
    var cacheItemPolicy = new CacheItemPolicy(); 
    cacheItemPolicy.ChangeMonitors.Add(new HostFileChangeMonitor(new[] { "app.config" })); 

    var innerAppSettingsLoader = container.GetInstance<IAppSettingsLoader>(); 
    return new CachedAppSettingsLoader(
     "AuthorizationRecords", 
     cacheItemPolicy, 
     MemoryCache.Default, 
     innerAppSettingsLoader); 
} 

Dies schlägt fehl, da einfacher Injector nicht meine Gewohnheit ResolveCachedAppSettingsLoader als Instanz Fabrik CachedAppSettingsLoader zu erkennen.

Der Konstruktor vom Typ CachedAppSettingsLoader enthält Parameter ‚CacheKey‘ vom Typ String, die für Konstruktor Injektion verwendet werden kann. Parametername: decoratorType

Meine Frage ist, wie kann ich eine benutzerdefinierte Func<CachedAppSettingsLoader> zu konstruieren, um dieses Caching Dekorateur (mit Abhängigkeiten) in der Einfachen Injector liefern?

Antwort

2

Der einfache Injektor erlaubt nicht einfach die Registrierung von Dekoratoren, die primitive Konfigurationswerte enthalten. Es gibt mehrere Möglichkeiten, Simple Injector zu erweitern, um ein solches Verhalten zu ermöglichen, aber ich würde sagen, dass es einfachere Lösungen gibt.

Mit Ausnahme der Erweiterung Simple Injector haben Sie hier grundsätzlich zwei Möglichkeiten. Entweder Sie greifen auf die manuelle Konstruktion dieses Teils des Objektdiagramms zurück oder Sie extrahieren die Gruppe primitiver Konfigurationswerte in ein eigenes Konfigurationsobjekt, das Sie als Singleton im Container registrieren können.

Sie können manuell den Dekorateur und seine decoratee konstruieren wie folgt:

container.RegisterSingleton<IAppSettingsLoader>(
    new CachedAppSettingsLoader(
     "AuthorizationRecords", 
     cacheItemPolicy, 
     MemoryCache.Default, 
     new FileAppSettingsLoader())); 

Die andere Option ist die Konfigurationswerte in die eigene Klasse zu extrahieren, die ohnehin gute Idee sein könnte:

public class CachedAppSettingsLoaderSettings 
{ 
    public ObjectCache Cache; 
    public CacheItemPolicy Policy; 
    public string CacheKey; 
} 

public class CachedAppSettingsLoader : IAppSettingsLoader 
{ 
    private readonly CachedAppSettingsLoaderSettings settings; 
    private readonly IAppSettingsLoader decoratee; 

    public CachedAppSettingsLoader(
     CachedAppSettingsLoaderSettings settings, IAppSettingsLoader decoratee) 
    { 
     ... 
    } 
} 

Nach diesem Refactoring können Sie Ihre Typen wie folgt registrieren:

container.Register<IAppSettingsLoader, FileAppSettingsLoader>(Lifestyle.Singleton); 
container.RegisterDecorator<IAppSettingsLoader, CachedAppSettingsLoader>(Lifestyle.Singleton); 
container.RegisterSingleton(new CachedAppSettingsLoaderSettings 
{ 
    Cache = MemoryCache.Default, 
    Policy = new CacheItemPolicy { ... }, 
    CacheKey = "AuthorizationRecords" 
}); 
+0

Ich war b asically das gleiche tun, wie Ihre erste Lösung :) aber Ihre zweite Lösung machte mehr Sinn für mich, wird versuchen, dass – rexcfnghk

+0

übrigens, wenn ich Ihre erste Option verwenden, wird die 'HostFileChangeMonitor' Instanz automatisch entsorgt werden, wenn es erlischt Umfang? – rexcfnghk

+0

In keinem Fall wird es vom Simple Injector entsorgt. Es weiß nichts darüber. – Steven

Verwandte Themen