2010-01-05 6 views
8

Tengo una aplicación de intranet personalizada que no tiene requisitos de interoperabilidad. Construimos programáticamente un canal NetTcp en modo dúplex para pasar mensajes. Queríamos cambiar la codificación del mensaje, pero no hemos podido averiguar cómo hacerlo.¿Cómo se modifica programáticamente la codificación del mensaje WCF para NetTcp?

El enfoque que hemos adoptado (sin éxito) ha sido extender la NetTcpBinding en una nueva clase llamada LeanTcpBinding de la siguiente manera:


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; 
    } 
} 

Obviamente, estamos tratando de reemplazar el BinaryMessageEncodingBindingElement por defecto con los nuestros. Sólo para obtener el uso iniciado, el LeanBinaryMessageEncodingBindingElement es una extensión de la BinaryMessageEncodingBindingElement de la siguiente manera:


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; } 
     } 
} 

Cuando trato de usar la unión que hace exactamente lo que yo creo que debería hacer ... que sustituye a la BinaryMessageEncodingBindingElement. Sin embargo, nunca recibo llamadas a LeanBinaryMessageEncodingBindingElement.CreateMessageEncoderFactory(), aunque se están intercambiando mensajes en el canal.

¿Alguien tiene alguna sugerencia sobre cómo hacer esto correctamente?

+0

¿Qué trataste de lograr? ¿Permanencia? ¿Ha mejorado? –

Respuesta

7

Kenny Wolf aclaró lo que faltaba y está documentado en la entrada del blog a continuación.

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

Para los impacientes, el problema es que por defecto el MessageEncoderBindingElement no sumarse a parámetros de fijación del contexto. Como resultado, cuando el transporte va más tarde a encontrar MessageEncoderBindingElement, no puede encontrar el que yo (o usted) ha creado y tiene la falla silenciosa que anoté en mi publicación original.

Desafortunadamente, deberá anular todos los métodos CanBuildXXX y BuildXXX de la siguiente manera para asegurarse de que está agregando el elemento de enlace a los parámetros de enlace del contexto.

 

     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

Lo siento si esta es una pregunta estúpida, pero ¿dónde colocaste este código? En el proxy del cliente? ¿Qué hay del lado del servidor? –

2

¿Ha intentado crear un CustomBinding en lugar de la configuración NetTcpBinding que tiene? Algo como esto:

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); 
+1

Probé ese método también. Todavía no se está llamando al método CreateMessageEncoderFactory() en LeanBinaryMessageEncodingBindingElement; el resultado es que mi codificador no se está construyendo en absoluto. Me falta algo obvio. – Ajaxx

+0

Esto funciona en .NET 4: D – markmnl

+0

@markmnl No funciona para mí en .Net 4.5.1 –

Cuestiones relacionadas