データアクセスレイヤー内のオブジェクトを何度も何度もコードに書き込むことに飽きてしまいました。C#で関数/メソッドをキャッシュする方法はありますか
関数に大きな変更を加えることなく、C#関数の結果をキャッシュすることはできますか?
現在、この機能をサポートするフレームワークはありますか?
独自の "c#関数属性"を記述することで同じファイルをアーカイブできますか?もしそうなら、実装を開始するためのいくつかの点を落とす?
データアクセスレイヤー内のオブジェクトを何度も何度もコードに書き込むことに飽きてしまいました。C#で関数/メソッドをキャッシュする方法はありますか
関数に大きな変更を加えることなく、C#関数の結果をキャッシュすることはできますか?
現在、この機能をサポートするフレームワークはありますか?
独自の "c#関数属性"を記述することで同じファイルをアーカイブできますか?もしそうなら、実装を開始するためのいくつかの点を落とす?
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です。ウィキペディアはこのテーマについてさらに詳しく述べています。残念ながら、それをサポートする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;
}
}
}
:
[Cache]
public virtual Customer GetCustomerByID(int customerID)
{
return CustomerRepository.GetCustomerByID(customerID);
}
例(Ninject & Ninject.Interception)
プロキシ/迎撃体制を使用しますインターセプトされた関数は仮想でなければならず、クラスは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