如何从另一个类的 CacheItemPolicy 上实现 UpdateCallback?
我有一个使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你可以这样做:
或者只是这样:
You can do this:
Or just this:
我认为你可以做到这一点
I think you can do this