2010-01-05 10 views
8

Ho un'applicazione Intranet personalizzata che non ha requisiti di interoperabilità. Costruiamo in modo programmatico un canale NetTcp in modalità duplex per il passaggio dei messaggi. Volevamo cambiare la codifica del messaggio ma non siamo stati in grado di capire come farlo accadere.Come si modifica la codifica dei messaggi WCF per NetTcp al livello di programmazione?

L'approccio che abbiamo preso (senza successo) è stato quello di estendere il NetTcpBinding in una nuova classe chiamata LeanTcpBinding come segue:


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

Ovviamente, stiamo cercando di sostituire il BinaryMessageEncodingBindingElement di default con la nostra. Solo per ottenere l'uso avviato, il LeanBinaryMessageEncodingBindingElement è un'estensione del BinaryMessageEncodingBindingElement come segue:


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

Quando provo ad usare l'associazione che fa esattamente quello che penso che dovrebbe fare ... sostituisce la BinaryMessageEncodingBindingElement. Tuttavia, non ricevo mai chiamate a LeanBinaryMessageEncodingBindingElement.CreateMessageEncoderFactory(), anche se i messaggi vengono scambiati attraverso il canale.

Qualcuno ha qualche suggerimento su come farlo correttamente?

+0

Cosa hai cercato di raggiungere? Permanenza? È migliorato? –

risposta

7

Kenny Wolf ha chiarito cosa mancava ed è documentato nel post di blog qui sotto.

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

Per gli impazienti, il problema è che di default il MessageEncoderBindingElement non si aggiunge ai parametri vincolanti del contesto. Di conseguenza, quando in seguito il trasporto va a trovare MessageEncoderBindingElement, non riesce a trovare quello che io (o tu) hai creato e ha l'errore silenzioso che ho notato nel mio post originale.

Sfortunatamente, è necessario eseguire l'override di tutti i metodi CanBuildXXX e BuildXXX come segue per assicurarsi di aggiungere l'elemento di associazione ai parametri di associazione del contesto.

 

     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

Mi dispiace se questa è una domanda stupida, ma dove hai posto questo codice? Nel proxy del cliente? E il lato server? –

2

Hai provato a creare una CustomBinding invece della configurazione NetTcpBinding che hai? Qualcosa del genere:

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

Ho provato anche questo metodo. Il metodo CreateMessageEncoderFactory() non viene ancora chiamato su LeanBinaryMessageEncodingBindingElement - il risultato è che il mio codificatore non viene affatto costruito. Mi manca qualcosa di ovvio. – Ajaxx

+0

Funziona in .NET 4: D – markmnl

+0

@markmnl Non funziona per me in .Net 4.5.1 –

Problemi correlati