1

考虑以下:

我有一台主服务器和几台位于不同位置的服务器,它们可以与主服务器通信。此外,(GUI)客户端可以连接到每个服务器。

所以我有一个众所周知的公共接口:

[ServiceContract(SessionMode = SessionMode.Required)]
public interface IBaseService
{
    [OperationContract]
    void Subscribe();

    [OperationContract]
    void Unsubscribe();
}

此外,服务器支持回调合约,以便主服务器可以在与其连接的服务器上触发请求。

[ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
interface IServerService : IBaseService
{
}

public interface ICallback
{
    [OperationContract]
    [FaultContract(typeof(ExceptionDetail))]
    void TheCallback();
}

这意味着服务器有 2 个已实施的合同。因此,当我在主服务器上迭代所有订阅者(在Subscribe我缓存所有)并为客户端调用回调合约时,它就会超时!OperationContext我曾预料到某种合同不匹配。除了操作超时之外的任何东西(并且立即!)?!?

我还试图找出客户端用于连接的合同名称(OperationContext.Current)。但这也没有成功。它IServerService在这两种情况下都说OperationContext.Current.EndpointDispatcher.ContractName

服务器端是否有可能OperationContract确定客户端在连接时使用了哪个?

当然,我可以通过一种方法扩展服务器接口,SubscribeServer但这对我来说似乎相当难看。

编辑

正如建议的那样,我确实实施了一个MessageInspector. 但是在AfterReceiveRequestIClientChannel中可以成功投到ICallback

更奇怪的是调用堆栈已经包含ReliableDuplexSessionChannel

>   XYZ.exe!XYZ.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) Line 99  C#
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.AfterReceiveRequestCore(ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x86 bytes 
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x37 bytes 
System.ServiceModel.dll!System.ServiceModel.Dispatcher.MessageRpc.Process(bool isOperationContextSet) + 0x151 bytes 
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext request, bool cleanThread, System.ServiceModel.OperationContext currentOperationContext) + 0x644 bytes 
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext request, System.ServiceModel.OperationContext currentOperationContext) + 0x1d2 bytes    
System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(System.IAsyncResult result) + 0x4b bytes 
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes  
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes 
System.Runtime.DurableInstancing.dll!System.Runtime.InputQueue<System.ServiceModel.Channels.Message>.AsyncQueueReader.Set(System.Runtime.InputQueue<System.ServiceModel.Channels.Message>.Item item) + 0x41 bytes   
System.Runtime.DurableInstancing.dll!System.Runtime.InputQueue<System.ServiceModel.Channels.Message>.Dispatch() + 0x320 bytes   
System.ServiceModel.dll!System.ServiceModel.Channels.ReliableDuplexSessionChannel.ProcessDuplexMessage(System.ServiceModel.Channels.WsrmMessageInfo info) + 0x7cb bytes 
System.ServiceModel.dll!System.ServiceModel.Channels.ServerReliableDuplexSessionChannel.ProcessMessage(System.ServiceModel.Channels.WsrmMessageInfo info) + 0x2a7 bytes 
System.ServiceModel.dll!System.ServiceModel.Channels.ReliableDuplexSessionChannel.HandleReceiveComplete(System.IAsyncResult result) + 0x1fa bytes   
System.ServiceModel.dll!System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnReceiveCompletedStatic(System.IAsyncResult result) + 0x86 bytes 
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes  
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes 
System.ServiceModel.dll!System.ServiceModel.Channels.ReliableChannelBinder<System.__Canon>.InputAsyncResult<System.__Canon>.OnInputComplete(System.IAsyncResult result) + 0x7a bytes    
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes  
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes 
System.ServiceModel.dll!System.ServiceModel.Channels.FramingDuplexSessionChannel.TryReceiveAsyncResult.OnReceive(System.IAsyncResult result) + 0xa9 bytes   
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes  
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes 
System.ServiceModel.dll!System.ServiceModel.Channels.SynchronizedMessageSource.ReceiveAsyncResult.OnReceiveComplete(object state) + 0x82 bytes  
System.ServiceModel.dll!System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(object state) + 0x175 bytes    
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) + 0x32 bytes  
System.dll!System.Net.LazyAsyncResult.Complete(System.IntPtr userToken) + 0xc5 bytes    
System.dll!System.Net.Security.NegotiateStream.ProcessFrameBody(int readBytes, byte[] buffer, int offset, int count, System.Net.AsyncProtocolRequest asyncRequest) + 0x126 bytes    
System.dll!System.Net.Security.NegotiateStream.ReadCallback(System.Net.AsyncProtocolRequest asyncRequest) + 0xea bytes  
System.dll!System.Net.FixedSizeReader.CheckCompletionBeforeNextRead(int bytes) + 0x32 bytes 
System.dll!System.Net.FixedSizeReader.ReadCallback(System.IAsyncResult transportResult) + 0x9c bytes    
System.Runtime.DurableInstancing.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) + 0x16b bytes 
System.ServiceModel.dll!System.ServiceModel.Channels.ConnectionStream.ReadAsyncResult.OnAsyncReadComplete(object state) + 0xa2 bytes    
System.ServiceModel.dll!System.ServiceModel.Channels.SocketConnection.AsyncReadCallback(bool haveResult, int error, int bytesRead) + 0x19b bytes    
System.Runtime.DurableInstancing.dll!System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(uint error, uint bytesRead, System.Threading.NativeOverlapped* nativeOverlapped) + 0x40 bytes  
mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x96 bytes    
[Native to Managed Transition]  

这是否意味着如果我的服务类实现了IServerService定义了回调合同的服务类,那么所有连接的客户端都通过双工代理进行路由?无论客户使用(或实施)的合同如何?

4

2 回答 2

0

在服务器端,另一个包含传入消息数据的对象是OperationContext.Current.Host.

您可以获得有关合同的信息。以下是一些可用的数据:

接口名称OperationContext.Current.Host.ImplementedContracts.FirstOrDefault().Value.Name

接口命名空间OperationContext.Current.Host.ImplementedContracts.FirstOrDefault().Value.Namespace

完整的合同类型名称OperationContext.Current.Host.ImplementedContracts.FirstOrDefault().Value.ContractType.FullName

您也可以使用Reflectionin OperationContext.Current.Host.Description.ServiceType,这是一种类型。

希望这可以帮助。

于 2016-12-06T12:40:11.753 回答
0

如果有2个合约,一个是双工的,一个不是,可以检查Channel类型是否是回调接口类型:

' we want to support optional callbacks, so this just returns nothing if the callback isn't what we are looking for
If TypeOf OperationContext.Current?.Channel Is TDuplexClientCallback Then
    Return OperationContext.Current?.GetCallbackChannel(Of TDuplexClientCallback)
Else
    Return Nothing
End If
于 2018-08-10T01:36:01.830 回答