私のアプリケーションはクライアント側のエンタープライズキャッシングを使用します。キャッシュ可能な呼び出しごとにコードを記述することを避けたいと思います。非同期呼び出しの場合でも、WCFクライアント側の呼び出しをキャッシュできるようなソリューションがあるかどうか疑問に思っています。WCFクライアントサイドキャッシングを配線しますか?
これはWCFの "動作"やその他の手段で行うことができますか?コード例?
私のアプリケーションはクライアント側のエンタープライズキャッシングを使用します。キャッシュ可能な呼び出しごとにコードを記述することを避けたいと思います。非同期呼び出しの場合でも、WCFクライアント側の呼び出しをキャッシュできるようなソリューションがあるかどうか疑問に思っています。WCFクライアントサイドキャッシングを配線しますか?
これはWCFの "動作"やその他の手段で行うことができますか?コード例?
残念ながら、私はあなた自身をロールバックする必要があると思います。私はWCFにクライアント側のキャッシュメカニズムが組み込まれているとは思わない。
this questionへの回答が役に立ちます。
サービスの呼び出しごとに明示的に実装しなくてもキャッシュしたい場合は、Policy Injectionアプリケーションブロックのキャッシングハンドラを検討してください。属性を使用して呼び出しをマークすることができ、ポリシーインジェクションブロックがキャッシングを処理します。
私はクライアント側のソリューションではなく、ホスト側のソリューションを探しています。 –
私はこれは、WCFサービスのクライアント(DataServiceClient)上の一般的な拡張メソッドを持つ他の日でした。アクションと関数を使用して実際のServiceClient呼び出しを渡します。最後のクライアントの使用構文が少しファンキー(あなたがラムダを好きではない場合)であるが、この方法は、FaultException /中止の折り返しとキャッシングを行います。クライアント側で
public static class ProxyWrapper
{
// start with a void wrapper, no parameters
public static void Wrap(this DataServiceClient _svc, Action operation)
{
bool success = false;
try
{
_svc.Open();
operation.Invoke();
_svc.Close();
success = true;
}
finally
{
if (!success)
_svc.Abort();
}
}
// next, a void wrapper with one generic parameter
public static void Wrap<T>(this DataServiceClient _svc, Action<T> operation, T p1)
{
bool success = false;
try
{
_svc.Open();
operation.Invoke(p1);
_svc.Close();
success = true;
}
finally
{
if (!success)
_svc.Abort();
}
}
// non-void wrappers also work, but take Func instead of Action
public static TResult Wrap<T, TResult>(this DataServiceClient _svc, Func<T, TResult> operation, T p1)
{
TResult result = default(TResult);
bool success = false;
try
{
_svc.Open();
result = operation.Invoke(p1);
_svc.Close();
success = true;
}
finally
{
if (!success)
_svc.Abort();
}
return result;
}
}
、我々はこのようにそれらを呼び出す必要があります:
internal static DBUser GetUserData(User u)
{
DataServiceClient _svc = new DataServiceClient();
Func<int, DBUser> fun = (x) => _svc.GetUserById(x);
return _svc.Wrap<int, DBUser>(fun, u.UserId);
}
ここの計画を参照してください。 WCF呼び出し用の包括的なラッパーセットが用意できたので、同じアイデアを使用していくつかのキャッシュを挿入することができます。私はここで "ローテク"に行って、ちょうどキャッシュキー名の文字列を投げ始めました...あなたは反射で、よりエレガントな何かを行うことができます。
public static TResult Cache<TResult>(this DataServiceClient _svc, string key, Func<TResult> operation)
{
TResult result = (TResult)HttpRuntime.Cache.Get(key);
if (result != null)
return result;
bool success = false;
try
{
_svc.Open();
result = operation.Invoke();
_svc.Close();
success = true;
}
finally
{
if (!success)
_svc.Abort();
}
HttpRuntime.Cache.Insert(key, result);
return result;
}
// uncaching is just as easy
public static void Uncache<T>(this DataServiceClient _svc, string key, Action<T> operation, T p1)
{
bool success = false;
try
{
_svc.Open();
operation.Invoke(p1);
_svc.Close();
success = true;
}
finally
{
if (!success)
_svc.Abort();
}
HttpRuntime.Cache.Remove(key);
}
今だけにアンキャッシュを読み込み、あなたにキャッシュを呼び出し、あなたの作成/更新/削除:私は何もサーバサイドを再コーディングする必要はありませんでしたので
// note the parameterless lambda? this was the only tricky part.
public static IEnumerable<DBUser> GetAllDBUsers()
{
DataServiceClient _svc = new DataServiceClient();
Func<DBUser[]> fun =() => _svc.GetAllUsers();
return _svc.Cache<DBUser[]>("AllUsers", fun);
}
私はちょうど私が、この方法が好きWCFプロキシコール(これは少しでも脆弱で/どこでも散在していることがわかっていました)。
あなた自身のWCFプロキシ規約と標準的なキャッシング手順で代用してください。すべての汎用ラッパーテンプレートを最初に作成する作業はたくさんありますが、2つまでのパラメータが必要でしたし、すべてのキャッシュ操作が単一の関数シグネチャ(今のところ)を共有するのに役立ちます。これがあなたのために働くのか、それとも改善があれば教えてください。
上記のソリューションと同様に、http://www.acorns.com.au/blog/?p=85(PolicyInjection on WCF Services)を参照してください。サービス名に一致するようにポリシーを指定することができます。
私はそれを知っています。それは、私はちょうど(サーバーではない)クライアント上でIOperationInvokerを実装する方法を知りませんでした。具体的には、デフォルトメソッドの代わりにIOperationInvokerのInvokeBeginメソッドが呼び出されるように、IOperationBehaviourでApplyClientBehaviorをコーディングする方法はわかりません。 –