【发布时间】:2015-02-23 19:41:43
【问题描述】:
我正在尝试编写一个简单的通用缓存,但在使用 System.Func 作为回调生成足够唯一的键时遇到了问题。
我理想中想要的是能够传递一些描述的可调用委托,以便缓存本身可以获取值,并从同一个表达式中确定一个键。现在我遇到了异常,因为我没有传入实现或继承自 MethodCallExpression 的参数。对于这种预期行为,我应该使用什么来代替 System.Func?
public class SimpleCacheKeyGenerator : ICacheKey
{
public string GetCacheKey<T>(Expression<Func<T>> action)
{
var body = (MethodCallExpression) action.Body; //!!! Exception Raised - action.Body is FieldExpression
ICollection<object> parameters = (from MemberExpression expression in body.Arguments
select
((FieldInfo) expression.Member).GetValue(
((ConstantExpression) expression.Expression).Value)).ToList();
var sb = new StringBuilder(100);
sb.Append(body.Type.Namespace);
sb.Append("-");
sb.Append(body.Method.Name);
parameters.ToList().ForEach(x =>
{
sb.Append("-");
sb.Append(x);
});
return sb.ToString();
}
}
public class InMemoryCache : ICacheService
{
private readonly ICachePolicy _cachePolicy;
private readonly ICacheKey _cacheKey;
public InMemoryCache(ICachePolicy cachePolicy, ICacheKey cacheKey)
{
_cachePolicy = cachePolicy;
_cacheKey = cacheKey;
}
public T Get<T>(Func<T> getItemCallback) where T : class
{
var cacheID = _cacheKey.GetCacheKey(() => getItemCallback);
var item = HttpRuntime.Cache.Get(cacheID) as T;
if (item == null)
{
item = getItemCallback();
if (_cachePolicy.RenewLeaseOnAccess)
{
HttpContext.Current.Cache.Insert(cacheID, getItemCallback, null, System.Web.Caching.Cache.NoAbsoluteExpiration, _cachePolicy.ExpiresAfter);
}
else
{
HttpContext.Current.Cache.Insert(cacheID, getItemCallback, null, DateTime.UtcNow + _cachePolicy.ExpiresAfter, System.Web.Caching.Cache.NoSlidingExpiration);
}
}
return item;
}
}
【问题讨论】:
-
表达式的类型
-
您是否有多个底层方法被 Func
包装用于相同类型的 T 返回值?如果不是,您可以获取 Func 的哈希码(相同的签名通常会产生相同的哈希码)或使用 T 的类型作为您的密钥。否则,它在什么上下文中确定将哪个方法作为 Func 传递?在那种情况下,有什么东西可以提供钥匙吗? -
这是对那个问题的回应吗:stackoverflow.com/questions/3766698/… ?