Как Вы программно изменяете кодирование сообщения WCF для NetTcp?

У меня есть пользовательское приложение интранет, которое не имеет никаких требований совместимости. Мы программно создаем канал 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 (), даже при том, что сообщениями обмениваются через канал.

У кого-либо есть какие-либо предложения о том, как сделать это правильно?

8
задан Ajaxx 5 January 2010 в 15:39
поделиться

2 ответа

Кенни Вульф уточнил, чего не хватает, и это задокументировано в записи блога ниже.

http://kennyw.com/?p=170

Для нетерпеливых проблема в том, что по умолчанию элемент 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();
        }

7
ответ дан 5 December 2019 в 19:00
поделиться

Попробовали ли вы создать пользовательскую привязку вместо нее из имеющейся конфигурации NetTcpBinding? Что-то вроде этого:

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);
2
ответ дан 5 December 2019 в 19:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: