使用ChannelFactoryを使用してファクトリのインスタンスを作成し、そのインスタンスをキャッシュします。必要に応じて、キャッシュされたアイチューンスからコミュニケーションチャネルを作成することができます。
複数のチャネルファクトリ(複数のサービスがありますか)が必要ですか?私の経験では、これがパフォーマンスの最大のメリットとなるでしょう。チャネルを作成することは、かなり安価な作業です。それは時間がかかる開始時にすべてを設定しています。
私は個々のチャンネルをキャッシュしません - 私はそれらを作成し、操作のために使用して、それらを閉じます。それらをキャッシュすると、タイムアウトしてチャネルに障害が発生し、それを中止して新しいチャネルを作成する必要があります。
シングルトンを使用してChannelFactoryを実装する理由がわからない場合、特に作成してキャッシュし、エンドポイントが1つしかない場合は特にそうです。
もう少し時間がある場合は、後でサンプルコードを投稿します。
UPDATE:コード例
ここでは、私が仕事でプロジェクトのためにこれを実装する方法の例です。私はChannelFactory<T>
を使っていました。私が開発していたアプリケーションは、いくつかのサービスを持つn-tierアプリケーションであり、さらに多くが追加されます。目標は、アプリケーションのライフサイクルごとにクライアントを作成し、必要に応じて通信チャネルを作成する簡単な方法を持つことでした。アイデアの基本は私のものではありません(私はウェブ上の記事から入手しました)が、私のニーズに合わせて実装を変更しました。
私は自分のアプリケーションに静的ヘルパークラスを持っています。そのクラス内には、辞書と、channelfファクトリから通信チャネルを作成するメソッドがあります。
ディクショナリは次のとおりです(オブジェクトは、サービスごとに1つずつ、異なるチャネルファクトリを含むため、値です)。この例では、「キャッシュ」をプレースホルダの一種として配置しています。使用しているキャッシングメカニズムに置き換えてください。
public static Dictionary<string, object> OpenChannels
{
get
{
if (Cache["OpenChannels"] == null)
{
Cache["OpenChannels"] = new Dictionary<string, object>();
}
return (Dictionary<string, object>)Cache["OpenChannels"];
}
set
{
Cache["OpenChannels"] = value;
}
}
次に、ファクトリインスタンスから通信チャネルを作成する方法です。このメソッドは、ファクトリが最初に存在するかどうかをチェックします。ファクトリが存在しない場合は作成し、辞書に入れてからチャネルを生成します。それ以外の場合は、単にファクトリのキャッシュされたインスタンスからチャネルを生成します。
public static T GetFactoryChannel<T>(string address)
{
string key = typeof(T.Name);
if (!OpenChannels.ContainsKey(key))
{
ChannelFactory<T> factory = new ChannelFactory<T>();
factory.Endpoint.Address = new EndpointAddress(new System.Uri(address));
factory.Endpoint.Binding = new BasicHttpBinding();
OpenChannels.Add(key, factory);
}
T channel = ((ChannelFactory<T>)OpenChannels[key]).CreateChannel();
((IClientChannel)channel).Open();
return channel;
}
私は仕事で使っているものからこの例を削除しました。この方法では、複数のバインディングを処理したり、認証用の資格情報を割り当てるなど、クライアントを生成するためのワンストップ・ショッピング・センターを利用できます。
最後に、アプリケーションで使用すると、一般的にチャネルを作成し、ビジネスを行い、必要に応じて終了します(または中止する)。例:
IMyServiceContract client;
try
{
client = Helper.GetFactoryChannel<IMyServiceContract>("http://myserviceaddress");
client.DoSomething();
// This is another helper method that will safely close the channel,
// handling any exceptions that may occurr trying to close.
// Shouldn't be any, but it doesn't hurt.
Helper.CloseChannel(client);
}
catch (Exception ex)
{
// Something went wrong; need to abort the channel
// I also do logging of some sort here
Helper.AbortChannel(client);
}
上記の例を参考にしてください。私はこれに類似した何かを生産現場で約1年間使用してきました。とてもうまく機能しています。私たちが遭遇した問題の99%は、通常、アプリケーション外のもの(私たちの直接の管理下にない外部クライアントまたはデータソース)に関連しています。
明確でないことやその他のご質問がある場合は教えてください。
#3の場合は、1つのチャネルファクトリだけを作成する必要があります。基本的には、お客様が保有するサービスエンドポイントごとに1つのチャネルファクトリを用意します。私の場合は、これまでに6層あり、主に2層に広がっています。あなたのケースでは、1つのアプリケーションだけを使用して1つのサービスしか持たない場合は、上でやっていることを単純に行うことができます。上記のコードは正しい軌道にあります。キャッシングはアプリのニーズに基づいて行われます。 – Tim
@Tim - あなたのご協力のすべてに感謝します。私は本当にそれを感謝します!私のケースでは、私のサービスがとてもシンプルであったという事実が、複数のエンドポイントが存在するこれらの他の例を見て混乱を引き起こしていたと思います。私は今=あまり混乱していない=ティムは素晴らしい仕事を説明した!ありがとう、相棒! – Didaxis
あなたは大歓迎です。私は助けてくれるとうれしいです - 幸せなコーディング! – Tim