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

发布于 2024-12-05 05:30:04 字数 3776 浏览 2 评论 0原文

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

I have a simple Cache attribute implemented using postsharp. When I set the cache policy I want to be able to set a update callback like below.

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

This is fine if I just want to do this:

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

However, I want to be able to pass in a delegate/method/ method name and parameters into dynamically and execute that. SO I would expect to see something like (obviously syntax is wrong):

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

**********UPDATE********

I got it working. Not the most elegant method, bud it works.

My Aspect code is as follows:

[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 is as follows:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一抹淡然 2024-12-12 05:30:04

你可以这样做:

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

You can do this:

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

Or just this:

private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry, 
                                             CacheEntryUpdateCallback method)
{
     ...
     policy.UpdateCallback = method;
     ...
     return policy;
}
拒绝两难 2024-12-12 05:30:04

我认为你可以做到这一点

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

I think you can do this

`
    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;
    }
'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文