Как программно добавить возможность обнаружения к службе и клиенту WCF
В этом разделе описано, как сделать службу Windows Communication Foundation (WCF) доступной для обнаружения. Он построен на основе образца Резидентное размещение.
Настройка образца службы существующего резидентного размещения для обнаружения
Откройте решение резидентного размещения в среде Visual Studio 2010. Образец находится в каталоге TechnologySamples\Basic\Service\Hosting\SelfHost.
Добавьте ссылку на проект службы
System.ServiceModel.Discovery.dll
. Может появиться следующее сообщение об ошибке: «System. ServiceModel.Discovery.dll или одна из его зависимостей требует наличия более поздней версии .NET Framework, чем версия, указанная в проекте …». Получив такое сообщение, щелкните проект в обозревателе решений правой кнопкой мыши и выберите Свойства. В окне Свойства проекта проверьте, что Требуемая версия .NET Framework равна .NET Framework, версия 4.Откройте файл 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 проверьте наличие хотя бы одной соответствующей службы и верните 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 https://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
Чтобы выйти, нажмите клавишу <ВВОД>.
Пример
Ниже приведен полный листинг кода для данного образца. Поскольку этот код построен на основе образца Резидентное размещение, в список включены только измененные файлы. Дополнительные сведения об образце резидентного размещения см. в разделе Инструкции по установке.
// 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();
}
}
}
См. также
Основные понятия
Общие сведения об обнаружении WCF
Модель объектов обнаружения WCF