WCF: делаем форму службой

WCF: делаем форму службой

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

Накидайте на формы элементы управления так, чтобы они выглядели следующим образом:

WCF: делаем форму службой

Файл 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;
    }
  }
}

Файл App.config:

<?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: делаем форму службой

В данной статье вы научились делать форму службой WCF.

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


Комментарии:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *