【问题标题】:How can I implement a UpdateCallback on a CacheItemPolicy from another class?如何在另一个类的 CacheItemPolicy 上实现 UpdateCallback?
【发布时间】:2013-09-19 18:01:20
【问题描述】:

我有一个使用 postsharp 实现的简单缓存属性。当我设置缓存策略时,我希望能够设置如下更新回调。

 private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry)
    {
        var policy = new CacheItemPolicy();

        switch (type)
        {
            case (CacheType.Absolute):
                policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(expiry);
                policy.UpdateCallback = new CacheEntryUpdateCallback(UpdateHandler);
                break;
            case (CacheType.Sliding):
                policy.SlidingExpiration = new TimeSpan(0, 0, 0, expiry);
                break;
        }

        return policy;
    }

如果我只想这样做,这很好:

 private static void UpdateHandler(CacheEntryUpdateArguments arguments)
    {
        throw new NotImplementedException();
    }

但是,我希望能够动态地将委托/方法/方法名称和参数传入并执行。所以我希望看到类似的东西(显然语法是错误的):

private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry Func<?,?> method)
    {
        var policy = new CacheItemPolicy();

        switch (type)
        {
            case (CacheType.Absolute):
                policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(expiry);
                policy.UpdateCallback = new CacheEntryUpdateCallback(method);
                break;
            case (CacheType.Sliding):
                policy.SlidingExpiration = new TimeSpan(0, 0, 0, expiry);
                break;
        }

        return policy;
    }

**********更新********

我让它工作了。不是最优雅的方法,但它确实有效。

我的Aspect代码如下:

[Serializable]
public sealed class CacheAttribute : MethodInterceptionAspect
{
    private readonly CacheType m_cacheType;
    private readonly int m_expiry;
    private readonly bool m_useCallBack;
    private KeyBuilder m_keyBuilder;

    public KeyBuilder KeyBuilder
    {

        get { return m_keyBuilder ?? (m_keyBuilder = new KeyBuilder()); }

    }

    public CacheAttribute(CacheType cacheType, int expiry, bool useCallBack)
    {
        m_cacheType = cacheType;
        m_expiry = expiry;
        m_useCallBack = useCallBack;
    }

    public CacheAttribute(CacheType cacheType, int expiry)
    {
        m_cacheType = cacheType;
        m_expiry = expiry;
        m_useCallBack = false;
    }


    //Method executed at build time.

    public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
    {

        KeyBuilder.MethodParameters = method.GetParameters();

        KeyBuilder.MethodName = string.Format("{0}.{1}", method.DeclaringType.FullName, method.Name);

    }

    public override void OnInvoke(MethodInterceptionArgs context)
    {
        object value;


        string key = KeyBuilder.BuildCacheKey(context, context.Arguments);
        if (!CacheHelper.Get(key, out value))
        {
            // Do lookup based on caller's logic. 
            context.Proceed();
            value = context.ReturnValue;
            var cacheObject = new CacheObject {CacheValue = value, Context = context};
            CacheHelper.Add(cacheObject, key, m_cacheType, m_expiry, m_useCallBack);
        }

        context.ReturnValue = value;
    }
}

我的回调如下:

  private static void UpdateHandler(CacheEntryUpdateArguments arguments)
    {
        CacheObject cacheObject = (CacheObject)arguments.Source.Get(arguments.Key);
        cacheObject.Context.Proceed();
        cacheObject.CacheValue = cacheObject.Context.ReturnValue;

        CacheItem updatedItem = new CacheItem(arguments.Key, cacheObject);
        arguments.UpdatedCacheItem = updatedItem;
    }

【问题讨论】:

  • 您能在问题中包含您的方面代码吗?我不明白你想要达到什么目的。 GetCachePolicy 方法是从哪里调用的,应用在哪里?

标签: c# caching aop postsharp


【解决方案1】:

你可以这样做:

private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry, 
                                    Action<CacheEntryUpdateArguments> method)
{
     ...
     policy.UpdateCallback = (a) => method(a);
     ...
     return policy;
}

或者只是这样:

private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry, 
                                             CacheEntryUpdateCallback method)
{
     ...
     policy.UpdateCallback = method;
     ...
     return policy;
}

【讨论】:

    【解决方案2】:

    我认为你可以做到这一点

    `
        private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry, Func method)
        {
            var policy = new CacheItemPolicy();
    
            switch (type)
            {
                case (CacheType.Absolute):
                        Action updateCallBackHandler = null;
                        updateCallBackHandler = delegate(CacheEntryUpdateArguments arguments)
                        {                         
                            var newData = FetchYourDataWithCustomParameters();
    
                            arguments.UpdatedCacheItem = new CacheItem(arguments.Key, newData);
                            arguments.UpdatedCacheItemPolicy = new CacheItemPolicy()
                            {
                                AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(expiry),
                                UpdateCallback = new CacheEntryUpdateCallback(updateCallBackHandler)
                            };
                        };
    
                        policy.UpdateCallback = new CacheEntryUpdateCallback(updateCallBackHandler);
    
                    break;
                case (CacheType.Sliding):
                    policy.SlidingExpiration = new TimeSpan(0, 0, 0, expiry);
                    break;
            }
    
            return policy;
        }
    '

    【讨论】:

      猜你喜欢
      • 2010-11-12
      • 2015-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-16
      • 2021-12-25
      • 2017-04-10
      相关资源
      最近更新 更多