我厌倦了一次又一次地写代码来缓存数据访问层中的对象.
无论如何都要缓存c#函数结果而不需要对函数进行太多更改.
目前是否有任何框架支持此功能?
我可以通过编写自定义"c#函数属性"来存档吗?如果是这样,请给我一些积分来开始实施?
Dre*_*sel 23
可能性1:使用IL编织
之前提到过Postsharp.
您也可以尝试MethodCache.Fody包.
可能性2:使用代理/拦截框架
示例(Ninject和Ninject.Interception):
public class CacheAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<CachingInterceptor>();
}
}
public class CachingInterceptor : IInterceptor
{
private ICache Cache { get; set; }
public CachingInterceptor(ICache cache)
{
Cache = cache;
}
public void Intercept(IInvocation invocation)
{
string className = invocation.Request.Target.GetType().FullName;
string methodName = invocation.Request.Method.Name;
object[] arguments = invocation.Request.Arguments;
StringBuilder builder = new StringBuilder(100);
builder.Append(className);
builder.Append(".");
builder.Append(methodName);
arguments.ToList().ForEach(x =>
{
builder.Append("_");
builder.Append(x);
});
string cacheKey = builder.ToString();
object retrieve = Cache.Retrieve<object>(cacheKey);
if (retrieve == null)
{
invocation.Proceed();
retrieve = invocation.ReturnValue;
Cache.Store(cacheKey, retrieve);
}
else
{
invocation.ReturnValue = retrieve;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以装饰这样的函数:
[Cache]
public virtual Customer GetCustomerByID(int customerID)
{
return CustomerRepository.GetCustomerByID(customerID);
}
Run Code Online (Sandbox Code Playgroud)
截获的函数必须是虚函数,并且必须由Ninject内核创建类.如果依赖性能,可以直接通过Castle.DynamicProxy(Ninject.Extensions.Interception.DynamicProxy在内部使用)代理类.
可能性3:使用表达式包装器
您可以将函数作为表达式传递,生成包含类,方法和参数信息的缓存键,并在缓存中找不到表达式(如果未找到).这比AOP/Proxy框架增加了更多的运行时开销,但对于简单的解决方案来说已足够.
private T CacheAction<T>(Expression<Func<T>> action, [CallerMemberName] string memberName = "") where T : class
{
MethodCallExpression body = (MethodCallExpression)action.Body;
ICollection<object> parameters = new List<object>();
foreach (MemberExpression expression in body.Arguments)
{
parameters.Add(((FieldInfo)expression.Member).GetValue(((ConstantExpression)expression.Expression).Value));
}
StringBuilder builder = new StringBuilder(100);
builder.Append(GetType().FullName);
builder.Append(".");
builder.Append(memberName);
parameters.ToList().ForEach(x =>
{
builder.Append("_");
builder.Append(x);
});
string cacheKey = builder.ToString();
T retrieve = Cache.Retrieve<T>(cacheKey);
if (retrieve == null)
{
retrieve = action.Compile().Invoke();
Cache.Store(cacheKey, retrieve);
}
return retrieve;
}
public Customer GetCustomerByID(int customerID)
{
return CacheAction(() => CustomerRepository.GetCustomerByID(customerID));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15765 次 |
| 最近记录: |