如何从另一个类实现CacheItemPolicy上的UpdateCallback ?

本文关键字:CacheItemPolicy 上的 UpdateCallback 实现 另一个 | 更新日期: 2023-09-27 18:08:57

我有一个使用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;
    }
}

My Callback如下:

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

如何从另一个类实现CacheItemPolicy上的UpdateCallback ?

你可以这样做:

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

我认为你可以做到

`
    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;
    }
'