方法: プログラムを使用して探索可能性に WCF サービスとクライアントを追加する
このトピックでは、Windows Communication Foundation (WCF) サービスを探索可能にする方法を説明します。 これは、自己ホストのサンプルに基づいています。
既存の自己ホスト サービス サンプルを探索用に構成するには
Visual Studio 2012 で自己ホスト ソリューションを開きます。 このサンプルは、TechnologySamples\Basic\Service\Hosting\SelfHost ディレクトリにあります。
System.ServiceModel.Discovery.dll
への参照をサービス プロジェクトに追加します。 エラー メッセージ "System. ServiceModel.Discovery.dll またはその依存ファイルに、プロジェクトに指定されているバージョンよりも新しいバージョンの .NET Framework が必要です" が表示されることがあります。このメッセージが表示された場合は、ソリューション エクスプローラーでプロジェクトを右クリックし、 [プロパティ] をクリックします。 [プロジェクトのプロパティ] ウィンドウで、[ターゲット フレームワーク] が .NET Framework 4.6.1 になっていることを確認します。Service.cs ファイルを開き、次の
using
ディレクティブを追加します。using System.ServiceModel.Discovery;
Main()
メソッドのusing
ステート内で、ServiceDiscoveryBehavior インスタンスをサービス ホストに追加します。public static void Main() { // Create a ServiceHost for the CalculatorService type. using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService))) { // Add a ServiceDiscoveryBehavior serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior()); // ... } }
ServiceDiscoveryBehavior は、それが適用されているサービスが探索可能であることを指定します。
UdpDiscoveryEndpoint を、ServiceDiscoveryBehavior を追加するコードの直後でサービス ホストに追加します。
// Add ServiceDiscoveryBehavior serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior()); // Add a UdpDiscoveryEndpoint serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
このコードは、探索メッセージを標準の UDP 探索エンドポイントに送信する必要があることを指定します。
探索を使用してサービスを呼び出すクライアント アプリケーションを作成するには
新しいコンソール アプリケーションを
DiscoveryClientApp
というソリューションに追加します。System.ServiceModel.dll
およびSystem.ServiceModel.Discovery.dll
への参照を追加します。GeneratedClient.cs ファイルおよび App.config ファイルを、既存のクライアント プロジェクトから新しい DiscoveryClientApp プロジェクトに追加します。 これを行うには、ソリューション エクスプローラーでこれらのファイルを右クリックし、 [コピー] を選択します。 [DiscoveryClientApp] プロジェクトを右クリックし、 [貼り付け] を選択します。
Program.cs を開きます。
次の
using
ディレクティブを追加します。using System.ServiceModel; using System.ServiceModel.Discovery; using Microsoft.ServiceModel.Samples;
FindCalculatorServiceAddress()
という静的メソッドをProgram
クラスに追加します。static EndpointAddress FindCalculatorServiceAddress() { }
このメソッドは、探索を使用して
CalculatorService
サービスを検索します。FindCalculatorServiceAddress
メソッド内で、新しい DiscoveryClient インスタンスを作成し、UdpDiscoveryEndpoint をコンストラクターに渡します。static EndpointAddress FindCalculatorServiceAddress() { // Create DiscoveryClient DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); }
これにより WCF は、DiscoveryClient クラスが、標準の UDP 探索エンドポイントを使用して探索メッセージを送受信する必要があることを認識します。
次の行では、Find メソッドを呼び出し、検索対象のサービス コントラクトを含む FindCriteria インスタンスを指定します。 ここでは、
ICalculator
を指定します。// Find ICalculatorService endpoints FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
Find への呼び出しの後で、一致するサービスが少なくとも 1 つあるかどうかを確認し、最初に一致したサービスの EndpointAddress を返します。 一致するサービスがない場合は
null
を返します。if (findResponse.Endpoints.Count > 0) { return findResponse.Endpoints[0].Address; } else { return null; }
InvokeCalculatorService
という名前の静的メソッドをProgram
クラスに追加します。static void InvokeCalculatorService(EndpointAddress endpointAddress) { }
このメソッドは、
FindCalculatorServiceAddress
から返されたエンドポイント アドレスを使用して、電卓サービスを呼び出します。InvokeCalculatorService
メソッド内で、CalculatorServiceClient
クラスのインスタンスを作成します。 このクラスは、自己ホストのサンプルで定義されます。 これは、Svcutil.exe を使用して生成されました。// Create a client CalculatorClient client = new CalculatorClient();
次の行では、クライアントのエンドポイント アドレスを、
FindCalculatorServiceAddress()
から返されたエンドポイント アドレスに設定します。// Connect to the discovered service endpoint client.Endpoint.Address = endpointAddress;
前の手順のコードの直後に、電卓サービスで公開されたメソッドを呼び出します。
Console.WriteLine("Invoking CalculatorService at {0}", endpointAddress); double value1 = 100.00D; double value2 = 15.99D; // Call the Add service operation. double result = client.Add(value1, value2); Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result); // Call the Subtract service operation. result = client.Subtract(value1, value2); Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result); // Call the Multiply service operation. result = client.Multiply(value1, value2); Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result); // Call the Divide service operation. result = client.Divide(value1, value2); Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result); Console.WriteLine(); //Closing the client gracefully closes the connection and cleans up resources client.Close();
Main()
クラスのProgram
メソッドにコードを追加して、FindCalculatorServiceAddress
を呼び出します。public static void Main() { EndpointAddress endpointAddress = FindCalculatorServiceAddress(); }
次の行では、
InvokeCalculatorService()
を呼び出し、FindCalculatorServiceAddress()
から返されたエンドポイント アドレスを渡します。if (endpointAddress != null) { InvokeCalculatorService(endpointAddress); } Console.WriteLine("Press <ENTER> to exit."); Console.ReadLine();
アプリケーションをテストするには
権限のレベルが高いコマンド プロンプトを開き、Service.exe を実行します。
コマンド プロンプトを開き、Discoveryclientapp.exe を実行します。
Service.exe からの出力は次のようになります。
Received Add(100,15.99) Return: 115.99 Received Subtract(100,15.99) Return: 84.01 Received Multiply(100,15.99) Return: 1599 Received Divide(100,15.99) Return: 6.25390869293308
Discoveryclientapp.exe からの出力は次のようになります。
Invoking CalculatorService at http://localhost:8000/ServiceModelSamples/service Add(100,15.99) = 115.99 Subtract(100,15.99) = 84.01 Multiply(100,15.99) = 1599 Divide(100,15.99) = 6.25390869293308 Press <ENTER> to exit.
例
このサンプルで使用されているコード全体の一覧を次に示します。 このコードは、自己ホストのサンプルに基づいているため、変更されたファイルのみが示されています。
// Service.cs
using System;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Discovery;
namespace Microsoft.ServiceModel.Samples
{
// See SelfHost sample for service contract and implementation
// ...
// Host the service within this EXE console application.
public static void Main()
{
// Create a ServiceHost for the CalculatorService type.
using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService)))
{
// Add the ServiceDiscoveryBehavior to make the service discoverable
serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());
// Open the ServiceHost to create listeners and start listening for messages.
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
}
}
}
}
// Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Discovery;
using Microsoft.ServiceModel.Samples;
using System.Text;
namespace DiscoveryClientApp
{
class Program
{
static EndpointAddress FindCalculatorServiceAddress()
{
// Create DiscoveryClient
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
// Find ICalculatorService endpoints
FindResponse findResponse = discoveryClient.Find(new FindCriteria(typeof(ICalculator)));
if (findResponse.Endpoints.Count > 0)
{
return findResponse.Endpoints[0].Address;
}
else
{
return null;
}
}
static void InvokeCalculatorService(EndpointAddress endpointAddress)
{
// Create a client
CalculatorClient client = new CalculatorClient();
// Connect to the discovered service endpoint
client.Endpoint.Address = endpointAddress;
Console.WriteLine("Invoking CalculatorService at {0}", endpointAddress);
double value1 = 100.00D;
double value2 = 15.99D;
// Call the Add service operation.
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
// Call the Subtract service operation.
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
// Call the Multiply service operation.
result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
// Call the Divide service operation.
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
Console.WriteLine();
//Closing the client gracefully closes the connection and cleans up resources
client.Close();
}
static void Main(string[] args)
{
EndpointAddress endpointAddress = FindCalculatorServiceAddress();
if (endpointAddress != null)
{
InvokeCalculatorService(endpointAddress);
}
Console.WriteLine("Press <ENTER> to exit.");
Console.ReadLine();
}
}
}