在另一个进程中处理WCF事件

Sko*_*der 4 c# wcf process wcf-client winforms

我有一个不可序列化的对象,我想从一个单独的进程访问.我环顾四周,似乎唯一可行的选择是使用WCF,但我不知道如何做到这一点,因为我是WCF的新手.如果我创建一个WCF服务,如何将WinForm"挂钩"到WCF服务中的各种事件中?例如,用户直接与WCF服务通信,我希望WinForm客户端得到通知.我怎么能知道用户何时使用WCF服务做了什么并让WinForm客户端接受了这个?

tom*_*ern 10

实现您正在寻找的方法是在您的服务上实现回调合同.然后,您的win-forms应用程序将能够"订阅"在服务上触发的事件(例如对对象的修改).

为此,您需要使用回调合同实现服务合同:

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

[ServiceContract(CallbackContract = typeof(IMyService_Callback))]
public interface IMyService
{
    [OperationContract]
    bool Subscribe();
}
Run Code Online (Sandbox Code Playgroud)

然后,您实现您的服务:

[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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在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;
    }
}    
Run Code Online (Sandbox Code Playgroud)

配置服务:

<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>
Run Code Online (Sandbox Code Playgroud)

为客户配置

<system.serviceModel>
  <client>
    <endpoint address="net.tcp://localhost:8000/MyService" 
              binding="netTcpBinding"
              contract="TestService.IMyService"
              name="NetTcpBinding_IMyService">
    </endpoint>
  </client>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)