无论如何在C#中缓存函数/方法

我厌倦了一次又一次地写代码来缓存数据访问层中的对象。

无论如何都要缓存c#函数结果而不需要对函数进行太多更改。

目前是否有任何框架支持此function?

我可以通过编写自定义“c#函数属性”来存档吗? 如果是这样,请给我一些积分来开始实施?

您可以使用PostSharp创建缓存属性。 这是一个例子。

可能性1:使用IL编织

之前提到过Postsharp。

您也可以尝试MethodCache.Fody包。

可能性2:使用代理/拦截框架

示例(Ninject和Ninject.Interception):

public class CacheAttribute : InterceptAttribute { public override IInterceptor CreateInterceptor(IProxyRequest request) { return request.Context.Kernel.Get(); } } 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(cacheKey); if (retrieve == null) { invocation.Proceed(); retrieve = invocation.ReturnValue; Cache.Store(cacheKey, retrieve); } else { invocation.ReturnValue = retrieve; } } } 

然后你可以装饰这样的函数:

 [Cache] public virtual Customer GetCustomerByID(int customerID) { return CustomerRepository.GetCustomerByID(customerID); } 

截获的函数必须是虚拟的,并且必须由Ninject内核创建类。 如果依赖性能,可以直接通过Castle.DynamicProxy(Ninject.Extensions.Interception.DynamicProxy内部使用)代理类。

可能性3:使用表达式包装器

您可以将函数作为表达式传递,生成包含类,方法和参数信息的缓存键,并在缓存中找不到表达式(如果未找到)。 这比AOP / Proxy框架增加了更多的运行时开销,但对于简单的解决方案来说已足够。

 private T CacheAction(Expression> action, [CallerMemberName] string memberName = "") where T : class { MethodCallExpression body = (MethodCallExpression)action.Body; ICollection parameters = new List(); 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(cacheKey); if (retrieve == null) { retrieve = action.Compile().Invoke(); Cache.Store(cacheKey, retrieve); } return retrieve; } public Customer GetCustomerByID(int customerID) { return CacheAction(() => CustomerRepository.GetCustomerByID(customerID)); } 

如果我认为你的问题是正确的,你想要的正确术语就是记忆 。 维基百科提供了有关该主题的更多细节。 不幸的是,没有提到支持它的C#库。

缓存应用程序块是Microsoft对.NET中缓存的内置库的回答。

Lazy在首次运行后存储它的值。 示例: http : //msdn.microsoft.com/en-us/vstudio/bb870976

我建议使用Spring.Net AOP。 它基本上创建了一个代理,并且可以从/向缓存重定向调用。 http://www.springframework.net/doc/reference/html/aop-quickstart.html

然后你可以得到类似的建议:

 public class CachingAroundAdvice : IMethodInterceptor { #region Variable Declarations private Priority priority = Priority.Normal; #endregion public object Invoke(IMethodInvocation invocation) { // declare local variables string cacheKey = string.Empty; object dataObject = null; // build cache key with some algorithm cacheKey = CreateCacheKey(invocation.Method, invocation.Arguments); // retrieve item from cache dataObject = CacheManager.Cache.GetData(cacheKey); // if the dataobject is not in cache proceed to retrieve it if (null == dataObject) { dataObject = invocation.Proceed(); // add item to cache CacheManager.Cache.Add(cacheKey, dataObject, CachePriority, null, Expiration); } // return data object return dataObject; }