Обработка событий WCF в другом процессе - PullRequest
4 голосов
/ 17 января 2012

У меня есть несериализуемый объект, к которому я хотел бы получить доступ из отдельного процесса. Я посмотрел вокруг, и кажется, что единственно возможный вариант - использовать WCF, но я не уверен, как это сделать, так как я новичок в WCF. Если я создаю службу WCF, как мне «привязать» WinForm к различным событиям в службе WCF? Например, пользователь общается со службой WCF напрямую, и я хотел бы, чтобы мой клиент WinForm был уведомлен. Как бы я мог узнать, когда пользователь что-то сделал со службой WCF, и клиент WinForm подхватил это?

1 Ответ

10 голосов
/ 17 января 2012

Способ достижения того, что вы ищете, заключается в реализации контракта на обратный вызов для вашего сервиса.Тогда ваше приложение win-формы сможет "подписаться" на события, запускаемые в службе (например, изменения вашего объекта).

Для этого вы реализуете контракт на обслуживание с контрактом обратного вызова:

[ServiceContract]
public interface IMyService_Callback
{
    [OperationContract(IsOneWay = true)]
    void NotifyClients(string message);
}

[ServiceContract(CallbackContract = typeof(IMyService_Callback))]
public interface IMyService
{
    [OperationContract]
    bool Subscribe();
}

Затем вы реализуете свой сервис:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class MyService : IMyService
{
    private List<IMyService_Callback> callbacks;

    public MyService()
    {
        this.callbacks = new List<IMyService_Callback>();
    }

    private void CallClients(string message)
    {
        callbacks.ForEach(callback => callback.NotifyClients(message));
    }

    public bool Subscribe()
    {
        var callback = OperationContext.Current.GetCallbackChannel<IMyService_Callback>();

        if (!this.callbacks.Contains(callback))
        {
            this.callbacks.Add(callback);
        }

        // send a message back to the client
        CallClients("Added a new callback");

        return true;
    }
}

В вашем клиенте winforms вам нужно реализовать только метод обратного вызова:

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
public partial class ServiceClient : Form, IMyService_Callback
{
    // Sync context for enabling callbacks
    SynchronizationContext uiSyncContext;

    public ServiceClient()
    {
        InitializeComponent(); //etc.

        uiSyncContext = SynchronizationContext.Current;

        // Create proxy and subscribe to receive callbacks
        var factory = new DuplexChannelFactory<IMyService>(typeof(ServiceClient), "NetTcpBinding_IMyService");
        var proxy = factory.CreateChannel(new InstanceContext(this));
        proxy.Subscribe();
    }

    // Implement callback method
    public void NotifyClients(string message)
    {
        // Tell form thread to update the message text field
        SendOrPostCallback callback = state => this.Log(message);

        uiSyncContext.Post(callback, "Callback");
    }

    // Just updates a form text field
    public void Log(string message)
    {
        this.txtLog.Text += Environment.NewLine + message;
    }
}    

Конфигурация для сервиса:

<system.serviceModel>
  <services>
    <service name="TestService.MyService" behaviorConfiguration="Normal">
      <endpoint 
        address="net.tcp://localhost:8000/MyService" 
        contract="TestService.IMyService" 
        binding="netTcpBinding" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="Normal" >
        <serviceDebug includeExceptionDetailInFaults="true"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

Конфиг для клиента

<system.serviceModel>
  <client>
    <endpoint address="net.tcp://localhost:8000/MyService" 
              binding="netTcpBinding"
              contract="TestService.IMyService"
              name="NetTcpBinding_IMyService">
    </endpoint>
  </client>
</system.serviceModel>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...