我们如何从类库调用WCF回调?

时间:2017-02-08 16:14:41

标签: c# wcf callback

我已实施wsDualHttpBinding行为Callback。这样可以正常运行。

我的服务配置

<behaviors>
  <serviceBehaviors>
    <behavior name="default">
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
<services>
  <service name="MyServiceNamespace" behaviorConfiguration="default">
    <endpoint address="" binding="wsDualHttpBinding" contract="MyServiceCoontract" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>
 <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>

我的服务合同

[ServiceContract(CallbackContract=typeof(IMQServiceCallBack))]
public interface IMQService
{
    [OperationContract]
    void PublishMessage(Message message);
}

public interface IMQServiceCallBack
{
    [OperationContract(IsOneWay = true)]
    void MessageAcked(string fileName);

   [OperationContract(IsOneWay = true)]
    void MessageNacked(string fileName);
}

我的服务

public class MQService : IMQService
{
    public IMQServiceCallBack CallBack
    {
        get
        {
            return OperationContext.Current.GetCallbackChannel<IMQServiceCallBack>();
        }
    }

    public void PublishMessage(Common.Message message)
    {
        var mqManager = MQManager.GetInstance();
        mqManager.PublishMessage(message);
        CallBack.MessageAcked(message.FileName);
    }
}

根据我的实现,回调在原则上运行良好。但是,我的回调调用不应该来自我的服务类,而是来自类库。

当我在类库中使用mqManager.PublishMessage(message)发布消息时,该库中已有回调用于确认。

我的MQManager课程

中的回调
void channel_BasicAcks()
{
    //need to invoke service call back from here
}

所以,基本上当在类库中调用channel_BasicAcks()回调时,我需要提醒我使用这个库的服务,以便服务反过来应该回调我的客户端。我对如何从类库中的回调方法提醒我的服务的中间步骤感到困惑。这里的任何方向都会对我有所帮助。

1 个答案:

答案 0 :(得分:0)

简短回答

没有好办法。

答案很长

基本问题是您只能使用OperationContext.Current从运行WCF服务的线程中访问回调通道。

有一个相当肮脏的解决方法,涉及使您的服务成为单身,将所有回调存储在服务实例中的静态成员中,并提供客户必须调用的某种注册服务操作为了接收回调。

这样的东西
[ServiceContract(CallbackContract=typeof(IMQServiceCallBack))]
public interface IMQService
{
    [OperationContract]
    void PublishMessage(Message message);

    [OperationContract]
    void Register();
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MQService : IMQService
{
    public static List<CallBack> callbacks;

    public void Register()
    {
        callbacks.Add(OperationContext.Current.GetCallbackChannel<IMQServiceCallBack>());
    }
}

然后,您可以从应用域的其他部分远程调用回调。像

这样的东西
var service = new MQService();
service.callbacks.ForEach((c) => {
    c.MessageAcked(someMessage)
});

说实话,这在很多层面上非常糟糕,除了最基本的应用之外,我不会推荐它。