我已经为某些自定义日志记录类型的功能实现了IClientMessageInspector
和IDispatchMessageInspector
。在使这一切变得更“可插入”的过程中,我的每个实现现在都调用其他具有CanProcess(object)
方法的代码。 (例如,有许多不同的插件,因此我需要找到一个可以处理Message
对象的插件。)
由于MyClientMessageInspector.BeforeSendRequest
和MyDispatchMessageInspector.AfterReceiveRequest
实现都使用System.ServiceModel.Channels.Message
类作为消息的实现接口,因此我需要一种可靠的方式来知道我拥有的“哪个”消息-一个在客户端上,还是一个从服务器?可悲的是,基础类BufferedMessage
和BodyWriterMessage
都被标记为内部,所以我不能使用它们。
我输入了我讨厌的字符串比较技巧,但是它有效
这是DispatchMessageInspector调用的我的CanProcess
方法:
public bool CanProcess(object testObject)
{
return (testObject != null)
&& (testObject is System.ServiceModel.Channels.Message)
&& (testObject.GetType().UnderlyingSystemType
.FullName == "System.ServiceModel.Channels.BufferedMessage");
}
这与ClientMessageInspector调用的相同:
public bool CanProcess(object testObject)
{
return (testObject != null)
&& (testObject is System.ServiceModel.Channels.Message)
&& (testObject.GetType().UnderlyingSystemType
.FullName == "System.ServiceModel.Channels.BodyWriterMessage");
}
有什么想法吗?我忽略了
Message.Properties
中的某些内容,还是Message
的另一个属性来区分它们?我完全讨厌这个字符串比较技巧。
最佳答案
您可以使用MessageHeaders进行自定义标识。
这是自定义WCF消息检查器的示例,其中填充了标头:
public class WCFMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
//in this sample I use predefined Guid to distinct specific client...
Guid clientId = new Guid("5DBD6E89-81F2-4786-BC93-2758A8368A5D");
MessageHeader<Guid> header = new MessageHeader<Guid>((Guid)clientId);
MessageHeader untyped = header.GetUntypedHeader("Identity", "http://www.MyCustomNamespace.com");
request.Headers.Add(untyped);
return null;
}
}
在接收端,您可以阅读以下消息标头:
MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
try
{
Guid clientId = headers.GetHeader<Guid>("Identity", "http://www.MyCustomNamespace.com");
if (clientId == new Guid("5DBD6E89-81F2-4786-BC93-2758A8368A5D")
{
//TODO: this is our target client, do your stuff here...
}
}
catch (Exception)
{
}
最佳实践还应将密钥字符串/ Guid放在单独的库中,并从那里读取值。