我厭倦了編寫相同的代碼,一次又一次地緩存數據訪問層中的對象。有沒有反正C#中的緩存函數/方法#
有沒有辦法緩存c#函數的結果,而沒有太多的功能改變。
有沒有任何框架支持此功能?
我可以通過編寫自定義「c#函數屬性」來存檔相同的內容嗎?如果是這樣,請給我一點啓動實施?
我厭倦了編寫相同的代碼,一次又一次地緩存數據訪問層中的對象。有沒有反正C#中的緩存函數/方法#
有沒有辦法緩存c#函數的結果,而沒有太多的功能改變。
有沒有任何框架支持此功能?
我可以通過編寫自定義「c#函數屬性」來存檔相同的內容嗎?如果是這樣,請給我一點啓動實施?
Cache Application block是微軟公司在.NET中用於緩存的內置庫的答案。
請注意,從企業庫6開始,該塊已經退役(請參閱http://msdn.microsoft.com/zh-cn/library/dn169621.aspx)。這是可以理解的,因爲這些功能可以在.NET 4.0以後的System.Runtime.Caching中找到(參見http://msdn.microsoft.com/en-us/library/system.runtime.caching(v=vs.100).aspx )。 – Philippe 2014-01-29 19:22:22
我建議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;
}
如果我看了你的問題是正確的,你想要的正確的術語是memoization。維基百科提供了關於這個主題的更多細節不幸的是,沒有提及支持它的C#庫。
可能性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;
}
}
}
然後,你可以裝飾功能:
[Cache]
public virtual Customer GetCustomerByID(int customerID)
{
return CustomerRepository.GetCustomerByID(customerID);
}
截獲的函數必須是虛擬的,並且類必須由Ninject內核創建。如果你依賴性能,你可以通過Castle.DynamicProxy直接代理類(它由Ninject.Extensions.Interception.DynamicProxy內部使用)。
可能性3:使用表達式包裝
你可以通過功能表達,產生含有緩存鍵類,方法和參數信息,並調用表達式,如果在緩存找不到。這比AOP /代理框架增加了更多的運行時間開銷,但對於簡單的解決方案來說就足夠了。
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));
}
「我厭倦了編寫相同的代碼,一次又一次地緩存數據訪問層中的對象。」 - 繼承也許? – 2011-02-08 04:30:10
不是繼承,不想編寫冗餘代碼來檢查緩存對象是否存在?然後調用實際對象或從緩存中取出。 任何方式「Yuriy Faktorovich」都很好地處理。這就是我正在尋找的 – Veeru 2011-02-08 06:17:24