c# - 如何使用 Simple Injector 注入(inject) CacheItemPolicy

标签 c# asp.net-mvc-4 dependency-injection simple-injector

我正在遵循一些做法 documented通过 steven并使用 Simple Injector .我有一个从 WCF 服务检索数据的查询,我想使用 ObjectCache 的实例缓存结果.

我定义了一个装饰器 CachingQueryHandlerDecorator<TQuery, TResult> :

public sealed class CachingQueryHandlerDecorator<TQuery, TResult>
    : IQueryHandler<TQuery, TResult>
    where TQuery : IQuery<TResult>
{
    private readonly IQueryHandler<TQuery, TResult> _handler;
    private readonly ObjectCache _cache;
    private readonly CacheItemPolicy  _policy;
    private readonly ILog _log;

    public CachingQueryHandlerDecorator(IQueryHandler<TQuery, TResult> handler,
                                        ObjectCache cache,
                                        CacheItemPolicy policy,
                                        ILog log)
    {
        _handler = handler;
        _cache = cache;
        _policy = policy;
        _log = log;
    }

    public TResult Handle(TQuery query)
    {
        var key = query.GetType().ToString();
        var result = (TResult) _cache[key];
        if (result == null)
        {
            _log.Debug(m => m("No cache entry for {0}", key));
            result = (TResult)_handler.Handle(query);
            if (!_cache.Contains(key))
                _cache.Add(key, result, _policy);
        }
        return result;
    }
}

SimpleInjectorInitializer.cs内我定义缓存和策略,并为特定查询添加装饰器:

container.RegisterSingle<ILog>(LogManager.GetCurrentClassLogger());
container.RegisterSingle<ObjectCache>(() => new MemoryCache("MyCache"));
container.RegisterSingle<CacheItemPolicy>(() => new CacheItemPolicy { AbsoluteExpiration = DateTime.Now.AddMinutes(1) } );
.
.
.
container.RegisterDecorator(typeof(IQueryHandler<,>),
    typeof(CachingQueryHandlerDecorator<,>),
    ctx => ctx.ServiceType.GetGenericArguments()[0] == typeof(MyQuery));

我面临的问题是我希望能够指定不同的 CacheItemPolicy用于不同的查询。我可以创建一个新的 ICachePolicy<TQuery>接口(interface),然后为每个不同的查询类型定义具体的类,但我希望有一种方法可以避免这种情况,并直接在初始化文件中定义每个查询的策略。

最佳答案

I could create a new ICachePolicy interface and then define concrete classes for each different query type

我认为这实际上是一个非常好的想法。您可以注册一个默认的通用实现,该实现注入(inject)到每个没有注册特定实现的装饰器中:

container.RegisterOpenGeneric(typeof(ICachePolicy<>), typeof(DefaultCachePolicy<>),
    Lifestyle.Singleton);

对于具有替代缓存策略的查询,您可以注册一个特定的实现:

container.RegisterSingle<ICachePolicy<MyQuery>>(new CachePolicy<MyQuery> 
{
    AbsoluteExpiration = DateTime.Now.AddHour(2)
});

另一种选择是使用描述缓存策略的属性来标记查询或其查询处理程序(这是我通常采用的方法):

[CachePolicy(AbsoluteExpirationInSeconds = 1 * 60 * 60)]
public class MyQuery : IQuery<string[]> { }

现在您不必注入(inject) ICachePolicy<T> ,但可以使用反射直接读取此元数据:

public sealed class CachingQueryHandlerDecorator<TQuery, TResult>
    : IQueryHandler<TQuery, TResult>
    where TQuery : IQuery<TResult>
{
    private static readonly bool shouldCache;
    private static readonly CachingPolicySettings policy;

    private readonly IQueryHandler<TQuery, TResult> _handler;
    private readonly ObjectCache _cache;
    private readonly ILog _log;

    static CachingQueryHandlerDecorator()
    {
        var attribute = typeof(TQuery).GetCustomAttribute<CachePolicyAttribute>();

        if (attribute != null)
        {
            shouldCache = true;
            policy = attribute.Policy;
        }
    }

    public CachingQueryHandlerDecorator(
        IQueryHandler<TQuery, TResult> handler,
        ObjectCache cache,
        ILog log)
    {
        _handler = handler;
        _cache = cache;
        _log = log;
    }

    public TResult Handle(TQuery query)
    {
        if (!shouldCache)
        {
            return this._handler.handle(query);
        }

        // do your caching stuff here.
    }

关于c# - 如何使用 Simple Injector 注入(inject) CacheItemPolicy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19803555/

相关文章:

c# - 为什么 GotFocus 事件不断从 Designer 中删除自身?

dependency-injection - Jersy2注入(inject)slf4j记录器

c# - DbContext 加载缓慢

c# - 在 .NET 中从混淆中排除构造函数

azure - Visual Studio 11 测试版与 Azure 一起使用吗?

c# - 在ViewModel、ASP.net MVC中定义 "Model"类型的属性好不好

javascript - 未捕获类型 : Undefined is not a function JS error

php - 依赖注入(inject)容器处理 PHP 网站的哪些部分?

java - 如何同时创建具有 Autowiring 和非 Autowiring 字段的构造函数?

c# - 如何获取Windows UWP ClaimedBarcodeScanner识别的二维码像素坐标