如何从另一个类实现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;
}
你可以这样做:
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;
}
'