虽然我的解决方案可能不是“正确的”,但严格来说(如果你问我的话,这实际上应该在 WCF 本身中修复),它有效,并且足以满足我的目的。
首先,声明一个新的端点行为,如下所示:
public class WcfDiscoveryAddressFixEndpointBehavior : IEndpointBehavior, IDispatchMessageInspector
{
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
// Attach ourselves to the MessageInspectors of reply messages
clientRuntime.CallbackDispatchRuntime.MessageInspectors.Add(this);
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
object messageProperty;
if (!OperationContext.Current.IncomingMessageProperties.TryGetValue(RemoteEndpointMessageProperty.Name, out messageProperty)) return null;
var remoteEndpointProperty = messageProperty as RemoteEndpointMessageProperty;
if (remoteEndpointProperty == null) return null;
// Extract message body
string messageBody;
using (var oldMessageStream = new MemoryStream())
{
using (var xw = XmlWriter.Create(oldMessageStream))
{
request.WriteMessage(xw);
xw.Flush();
messageBody = Encoding.UTF8.GetString(oldMessageStream.ToArray());
}
}
// Replace instances of 0.0.0.0 with actual remote endpoint address
messageBody = messageBody.Replace("0.0.0.0", remoteEndpointProperty.Address);
// NOTE: Do not close or dispose of this MemoryStream. It will be used by WCF down the line.
var newMessageStream = new MemoryStream(Encoding.UTF8.GetBytes(messageBody));
XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(newMessageStream, new XmlDictionaryReaderQuotas());
// Create a new message with our modified endpoint address and
// copy over existing properties and headers
Message newMessage = Message.CreateMessage(xdr, int.MaxValue, request.Version);
newMessage.Properties.CopyProperties(request.Properties);
newMessage.Headers.CopyHeadersFrom(request.Headers);
request = newMessage;
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
}
此终结点行为将原始 WCF 发现回复消息替换为副本,其中的实例0.0.0.0
已替换为接收消息的地址,可在RemoteEndpointMessageProperty
's Address
财产。
要使用它,只需将新的端点行为添加到UdpDiscoveryEndpoint
当你创建的时候DiscoveryClient
:
var udpDiscoveryEndpoint = new UdpDiscoveryEndpoint();
udpDiscoveryEndpoint.EndpointBehaviors.Add(new WcfDiscoveryAddressFixEndpointBehavior());
_discoveryClient = new DiscoveryClient(udpDiscoveryEndpoint);
// Proceed as usual.