我有一个没有互操作性要求的自定义Intranet应用程序。我们以双工模式编程构造NetTcp通道以传递消息。我们想要改变消息编码,但却无法弄清楚如何实现这一点。
我们采取的方法(失败)是将NetTcpBinding扩展为一个名为LeanTcpBinding的新类,如下所示:
internal class LeanTcpBinding : NetTcpBinding
{
private static readonly ILog _log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public override BindingElementCollection CreateBindingElements()
{
BindingElementCollection bindingElementCollection = base.CreateBindingElements();
BindingElement encodingElement = bindingElementCollection.FirstOrDefault(
bindingElement => bindingElement is BinaryMessageEncodingBindingElement);
if (encodingElement != null)
{
int index = bindingElementCollection.IndexOf(encodingElement);
bindingElementCollection.RemoveAt(index);
bindingElementCollection.Insert(index, new LeanBinaryMessageEncodingBindingElement());
}
else
{
_log.Warn("Encoding not found");
}
return bindingElementCollection;
}
}
显然,我们正在尝试用我们自己的替换默认的BinaryMessageEncodingBindingElement。为了开始使用,LeanBinaryMessageEncodingBindingElement是BinaryMessageEncodingBindingElement的扩展,如下所示:
internal class LeanBinaryMessageEncodingBindingElement : MessageEncodingBindingElement
{
private readonly BinaryMessageEncodingBindingElement _bindingElement;
///
/// Initializes a new instance of the class.
///
public LeanBinaryMessageEncodingBindingElement()
{
_bindingElement = new BinaryMessageEncodingBindingElement();
}
///
/// Initializes a new instance of the class.
///
/// The binding element.
public LeanBinaryMessageEncodingBindingElement(BinaryMessageEncodingBindingElement bindingElement)
{
_bindingElement = bindingElement;
}
///
/// Initializes a new instance of the class.
///
/// The element to be cloned.
/// The binding element.
public LeanBinaryMessageEncodingBindingElement(MessageEncodingBindingElement elementToBeCloned, BinaryMessageEncodingBindingElement bindingElement)
: base(elementToBeCloned)
{
_bindingElement = bindingElement;
}
///
/// When overridden in a derived class, returns a copy of the binding element object.
///
///
/// A object that is a deep clone of the original.
///
public override BindingElement Clone()
{
return new LeanBinaryMessageEncodingBindingElement(
(BinaryMessageEncodingBindingElement)_bindingElement.Clone());
}
///
/// When overridden in a derived class, creates a factory for producing message encoders.
///
///
/// The used to produce message encoders.
///
public override MessageEncoderFactory CreateMessageEncoderFactory()
{
return new LeanBinaryMessageEncoderFactory(_bindingElement.CreateMessageEncoderFactory());
}
///
/// When overridden in a derived class, gets or sets the message version that can be handled by the message encoders produced by the message encoder factory.
///
///
/// The used by the encoders produced by the message encoder factory.
///
public override MessageVersion MessageVersion
{
get { return _bindingElement.MessageVersion; }
set { _bindingElement.MessageVersion = value; }
}
}
当我尝试使用绑定时,它完全按照我认为它应该做的...它取代了BinaryMessageEncodingBindingElement。但是,即使通过通道交换消息,我也永远不会调用LeanBinaryMessageEncodingBindingElement.CreateMessageEncoderFactory()。
有人对如何正确地做这件事有任何建议吗?
答案 0 :(得分:7)
肯尼·沃尔夫澄清了遗漏的内容,并在下面的博客文章中进行了记录。
对于不耐烦的人,问题是默认情况下MessageEncoderBindingElement不会将自身添加到上下文的绑定参数中。结果,当传输后来找到MessageEncoderBindingElement时,它找不到我(或你)创建的那个,并且我在原始帖子中注意到了无声失败。
不幸的是,您必须按如下方式覆盖所有CanBuildXXX和BuildXXX方法,以确保将绑定元素添加到上下文的绑定参数中。
public override bool CanBuildChannelFactory(BindingContext context)
{
if (context == null) {
throw new ArgumentNullException("context");
}
context.BindingParameters.Add(this);
return context.CanBuildInnerChannelFactory();
}
public override bool CanBuildChannelListener(BindingContext context)
{
if (context == null) {
throw new ArgumentNullException("context");
}
context.BindingParameters.Add(this);
return context.CanBuildInnerChannelListener();
}
public override IChannelFactory BuildChannelFactory(BindingContext context)
{
if (context == null) {
throw new ArgumentNullException("context");
}
context.BindingParameters.Add(this);
return context.BuildInnerChannelFactory();
}
public override IChannelListener BuildChannelListener(BindingContext context)
{
if (context == null) {
throw new ArgumentNullException("context");
}
context.BindingParameters.Add(this);
return context.BuildInnerChannelListener();
}
答案 1 :(得分:2)
您是否尝试过使用NetTcpBinding配置创建CustomBinding?像这样:
NetTcpBinding binding = new NetTcpBinding(); // get binding from somewhere
var elements = binding.CreateBindingElements();
BindingElementCollection newElements = new BindingElementCollection();
foreach ( var e in elements ) {
if ( e is MessageEncodingBindingElement ) {
newElements.Add(new MyMessageEncodingBindingElement());
} else {
newElements.Add(e);
}
}
CustomBinding cb = new CustomBinding(newElements);