2017-02-08 10 views
1

Я внедрил wsDualHttpBinding с поведением Callback. Это прекрасно работает без каких-либо проблем.Как мы вызываем обратный вызов WCF из библиотеки классов?

My Service Config

<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() обратного вызова вызывается в библиотеке классов, мне нужно, чтобы предупредить мою службу, которая потребляет эту библиотеку, так что служба в свою очередь, должен перезвонить моего клиента. Я зациклился на среднем шаге о том, как предупредить мою службу по методу обратного вызова в библиотеке классов. Любое направление здесь поможет мне.

ответ

0

Короткого ответ

Там нет хорошего способа сделать это.

Длинный ответ

Основная проблема заключается в том, что вы можете получить доступ только канал обратного вызова из в потоке под управлением службы WCF, используя OperationContext.Current.

Существует довольно грязный обходной путь, который предполагает создание вашей службы синглтона, сохраняя все функции обратного вызова в статический член внутри вашего экземпляра службы, а также предоставление какой-то регистрации операции обслуживания, которые клиенты должны позвонить, чтобы получить обратные вызовы ,

Что-то вроде

[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) 
}); 

Это довольно ужасно на очень многих уровнях, чтобы быть честным, и я бы не рекомендовал его для чего-нибудь, кроме самых простых приложений.

+0

Да, я понял, что нет способа. Но, еще много раз я был побежден, когда я думал, что нет способа, SO говорит, что есть способ :) Я переместил свой интерфейс обратного вызова в библиотеку классов, передал мой OperationContext в эту библиотеку, чтобы сама библиотека могла вызвать обратный вызов для клиентов – techspider