在简单的喷油器基本配置依赖注册装饰

问题描述 投票:3回答:1

我有一个抽象了文件IO加载我IAppSettingsLoader文件的app.config接口。

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

我有一个加载实际文件中的类:

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

然后,我有试图监视文件更改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;
    }
}

我试图注册没有成功的简单注射器这种缓存装饰。这是我的尝试:

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);
}

失败的原因是简单的注射器没有认识到我的自定义ResolveCachedAppSettingsLoader作为一个实例工厂CachedAppSettingsLoader

型CachedAppSettingsLoader的构造包含不能被用于构造子注入String类型的参数“cacheKey”。参数名:decoratorType

我的问题是如何能够提供一个定制Func<CachedAppSettingsLoader>在简单的喷油器来构建这个缓存​​装饰(与依赖关系)?

c# .net dependency-injection simple-injector
1个回答
4
投票

简单的喷油器不容易允许注册包含原始配置值装饰。有多种方式来扩展简单的喷油器,使这样的行为,但我要说的是,有更容易的解决方案。

除了扩展简单喷油器,你基本上有两个选择这里。要么你回退到对象图的这一部分的结构手册,或者提取组原始配置值到它自己的配置对象,它可以作为在容器中单寄存器。

您可以手动构建装饰和decoratee如下:

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

另一种选择是提取配置值到自己的类,这可能是个好主意呢:

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)
    {
        ...
    }
}

这个重构后,可以按如下所示注册你的类型:

container.Register<IAppSettingsLoader, FileAppSettingsLoader>(Lifestyle.Singleton);
container.RegisterDecorator<IAppSettingsLoader, CachedAppSettingsLoader>(
    Lifestyle.Singleton);
container.RegisterInstance(new CachedAppSettingsLoaderSettings
{
    Cache = MemoryCache.Default,
    Policy = new CacheItemPolicy { ... },
    CacheKey = "AuthorizationRecords" 
});
© www.soinside.com 2019 - 2024. All rights reserved.