데이터 액세스 레이어에서 객체를 캐시하기 위해 코드를 반복해서 작성하는 것이 지겨워졌습니다.어쨌든 C#에서 함수/메소드를 캐시 할 수 있습니까?
어쨌든 기능을 많이 변경하지 않고도 C# 함수 결과를 캐시 할 수 있습니까?
현재이 기능을 지원하는 프레임 워크가 있습니까?
사용자 정의 "C# function attributes"를 작성하여 동일하게 보관할 수 있습니까? 그렇다면 구현을 시작하기 위해 몇 가지 사항을 알려주십시오.
데이터 액세스 레이어에서 객체를 캐시하기 위해 코드를 반복해서 작성하는 것이 지겨워졌습니다.어쨌든 C#에서 함수/메소드를 캐시 할 수 있습니까?
어쨌든 기능을 많이 변경하지 않고도 C# 함수 결과를 캐시 할 수 있습니까?
현재이 기능을 지원하는 프레임 워크가 있습니까?
사용자 정의 "C# function attributes"를 작성하여 동일하게 보관할 수 있습니까? 그렇다면 구현을 시작하기 위해 몇 가지 사항을 알려주십시오.
Cache Application block은 .NET의 캐싱 용 내장 라이브러리에 대한 Microsoft의 대답입니다.
엔터 프라이즈 라이브러리 6, 그 블록을 은퇴했다 (참고 http://msdn.microsoft.com/en-us/library/dn169621.aspx) 참고. 그것은 .NET 4.0 이후 System.Runtime.Caching에서 기능을 찾을 수 있기 때문에 이해할 수 있습니다 (http://msdn.microsoft.com/en-us/library/system.runtime.caching(v=vs.100).aspx 참조).). – Philippe
나는 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입니다. Wikipedia에서는이 주제에 대해 자세히 설명합니다. 불행히도이를 지원하는 C# 라이브러리에 대한 참조는 없습니다.
http://code.google.com/p/mbcache – Roger
가능성 1 : IL 제직
Postsharp은 앞서 언급되었다.
MethodCache.Fody 패키지를 사용해 볼 수도 있습니다.
가능성 2 :
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;
}
}
}
그런 다음 당신이 장식 수있는 기능과 같은 :
예 (Ninject에 & Ninject.Interception)는 프록시/차단 프레임 워크를 사용
[Cache]
public virtual Customer GetCustomerByID(int customerID)
{
return CustomerRepository.GetCustomerByID(customerID);
}
을 차단 된 기능은 가상이어야하며 클래스는 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));
}
"데이터 액세스 레이어에서 객체를 다시 캐시하기 위해 코드를 작성하는 것과 같은 방법으로 지루해졌습니다."- 상속 가능성이 있습니까? –
상속, 캐시 개체가 있는지 여부를 확인하기 위해 중복 코드를 쓰지 않으시겠습니까? 실제 객체를 호출하거나 캐시에서 가져옵니다. "Yuriy Faktorovich"는 모든면에서 훌륭하게 해결되었습니다. 그게 내가 정확히 찾고있는거야 – Veeru