【发布时间】: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 方法是从哪里调用的,应用在哪里?