WCF: делаем форму службой
Всем доброго времени суток. На связи Алексей Гулынин. Продолжаем работать с WCF. Часто возникает вопрос: как службе получить ссылку на форму, т.е. получить доступ к пользовательскому интерфейсу? Одним из вариантов будет сделать саму форму службой. Мы создаём форму, которая будет реализовывать контракт. Создадим простое Windows Forms-приложение, которое будет состоять из серверной и клиентской частей.
Накидайте на формы элементы управления так, чтобы они выглядели следующим образом:

Файл IContract.cs (наш контракт) добавляем в оба проекта. Не забываем подключать System.ServiceModel:
[ServiceContract]
interface IContract
{
[OperationContract]
string Print(string str);
}
Клиентский код будет выглядеть следующим образом:
using System;
using System.ServiceModel;
using System.Windows.Forms;
namespace Client
{
public partial class Form1 : Form
{
// Адрес
Uri address = new Uri("http://localhost:343/IContract");
// Привязка
BasicHttpBinding binding = new BasicHttpBinding();
// Фабрика каналов, один из которых будет реализовать контракт
ChannelFactory<IContract> factory;
// Ссылка на канал.
IContract channel;
public Form1()
{
InitializeComponent();
}
private void btn_Send_Click(object sender, EventArgs e)
{
try
{
if (factory == null)
{
factory = new ChannelFactory<IContract>(binding, new EndpointAddress(address));
// Создаём канал
channel = factory.CreateChannel();
}
if (factory != null && channel != null)
{
tB_Client_Info.Text += "Моё сообщение: " + tB_Client_Send.Text + Environment.NewLine;
// Здесь уже сервер отправляет сообщение клиенту
tB_Client_Info.Text += "Сообщение с сервера: " + channel.Print(tB_Client_Send.Text) + Environment.NewLine;
// Обнуляем поле с текстом для отправки сообщения
tB_Client_Send.Text = "";
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
Код серверной части:
using System;
using System.Windows.Forms;
using System.ServiceModel;
namespace Server
{
// Это означает, что экземпляр данного класса будет являться единственным.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
// Здесь как раз указываем, что форма реализует интерфейс
public partial class Form1 : Form, IContract
{
// Ссылка на экземпляр ServiceHost.
ServiceHost serviceHost;
public Form1()
{
InitializeComponent();
}
private void btn_Start_Click(object sender, EventArgs e)
{
try
{
// Если хост ещё не запущен
if (serviceHost == null)
{
// Создание экземпляра ServiceHost
// Здесь мы передаём экземпляр самой формы
serviceHost = new ServiceHost(this);
// Ждём прихода новых сообщений
serviceHost.Open();
tB_Server_Info.Text += "Сервер запущен." + Environment.NewLine;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btn_Stop_Click(object sender, EventArgs e)
{
try
{
// Если уже хост запущен
if (serviceHost != null)
{
// Останавливаем сервер
serviceHost.Close();
serviceHost = null;
tB_Server_Info.Text += "Сервер остановлен." + Environment.NewLine;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// Реализуем контракт (определяем метод Print)
public string Print(string str)
{
tB_Server_Info.Text += "От клиента пришло сообщение: " + str + Environment.NewLine;
return "Сообщение клиента: " + str;
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name ="Server.Form1">
<host>
<baseAddresses>
<add baseAddress="http://localhost:343/IContract"/>
</baseAddresses>
</host>
<!-- указываем адрес, привязку и контракт -->
<endpoint address=""
binding="basicHttpBinding"
contract="Server.IContract" />
</service>
</services>
</system.serviceModel>
</configuration>
Сначала запускаем сервер, а далее клиента. Видим, что всё корректно работает:

В данной статье вы научились делать форму службой WCF.
На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.




