【问题标题】:Getting InvalidCastException on GetCallbackChannel在 GetCallbackChannel 上获取 InvalidCastException
【发布时间】:2019-07-11 03:58:45
【问题描述】:

我正在使用 WCF 进行双工通信。意图是能够在客户端应用程序和 Windows 服务之间来回发送消息。来自客户端应用程序的通信工作正常,但每当我尝试获取回调服务时,尝试使用回调通道从服务返回到客户端的通信都会失败,并出现 InvalidCastException。

服务合同:

[ServiceContract(CallbackContract=typeof(IPipeListenerCallbackService), SessionMode=SessionMode.Required)]
public interface IPipeListenerService
{
    [OperationContract(IsOneWay=true)]
    void SendMessage(string message);
}

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

实施:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class PipeListenerService : IPipeListenerService
{
    public void SendMessage(string message)
    {
        //do something...
    }


    public IPipeListenerCallbackService Callback
    {
        get
        {
            return OperationContext.Current.GetCallbackChannel<IPipeListenerCallbackService>();
        }
    }

}

托管/打开 WCF ServiceHost 的服务代码:

try
{
    PipeListenerService service = new PipeListenerService();
    Uri pipeLocation = new Uri("net.pipe://localhost/" + this.PipeName);

    this.pipeServiceHost = new ServiceHost(service, pipeLocation);
    NetNamedPipeBinding binding = new NetNamedPipeBinding();
    this.pipeServiceHost.AddServiceEndpoint(typeof(IPipeListenerService), binding, "MessagePipe");

    this.pipeServiceHost.Open();                
}
catch (Exception ex)
{
    //do proper error handling here                
}

在服务代码的其他地方,我要在回调上实际调用 SendMessage,所以我正在执行以下操作:

PipeListenerService theService = this.pipeServiceHost.SingletonInstance as PipeListenerService;
if (theService != null)
{
   theService.Callback.SendMessage(message);
}

在获取回调属性的地方抛出异常。

例外是:

System.InvalidCastException:无法将“System.ServiceModel.Channels.ServiceChannel”类型的对象转换为“CommUtil.IPipeListenerCallbackService”类型。 在 System.ServiceModel.OperationContext.GetCallbackChannelT 在 .PipeListenerService.get_Callback()

作为参考,我在消化 MSDN 上关于 WCF 的双工服务 found here 的文章后创建了这个。我的 google-fu 只显示了“将第二个合同包含为 CallbackContract”之类的链接,我认为我已经在这样做了。

欢迎提出任何建议,包括可能的替代方法。一个限制是,因为客户端应用程序必须作为普通用户(不是管理员/提升权限)运行,我不能简单地做 2 个单独的管道,一个由服务托管,另一个由客户端托管,因为 WCF 安全限制将使客户端的管道对其他进程不可见。

【问题讨论】:

    标签: c# wcf


    【解决方案1】:

    找到我自己问题的答案。

    本质上,我的问题是我没有将回调对象保存在其生命周期的正确位置。

    查看提供的示例,所有回调都被用作对入站服务调用的响应/回复。在我的情况下,如果我要在 SendMessage() 中获取它。

    查看更多示例,我找到了一个用于发布者/订阅者设计模式here 的示例。关键区别在于它会在调用一个方法(在本例中为订阅)期间保存回调对象,并在其他地方使用它。

    以下相关代码示例:

    public void Subscribe()  
        {  
            callback = OperationContext.Current.GetCallbackChannel<ISampleClientContract>();  
            priceChangeHandler = new PriceChangeEventHandler(PriceChangeHandler);  
            PriceChangeEvent += priceChangeHandler;  
        }  
    
    public void PriceChangeHandler(object sender, PriceChangeEventArgs e)  
        {  
            callback.PriceChange(e.Item, e.Price, e.Change);  
        }  
    

    因此,在我的具体情况下,我想要的行为/解决方案更接近于发布/订阅模式,而不是调用和响应模式。所以,我只需要添加一个额外的服务方法,Register(),它将保存回调对象,并让客户端在建立连接通道后调用该服务方法。

    【讨论】:

      猜你喜欢
      • 2013-04-13
      • 1970-01-01
      • 2021-12-12
      • 2017-03-31
      • 2019-07-01
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多