2011-01-07 5 views
5

Ho uno stream che contiene del testo, ora voglio modificare del testo (sostituire alcuni valori) in quel flusso.Come posso modificare il testo in un flusso in modo efficiente, in un componente della pipeline BizTalk?

Qual è il modo più efficiente per farlo, quindi senza interrompere il flusso? Voglio utilizzarlo in un componente della pipeline personalizzato per BizTalk.

public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg) 
{ 
    string msg = ""; 
    using (VirtualStream virtualStream = new VirtualStream(pInMsg.BodyPart.GetOriginalDataStream())) 
    { 
     using(StreamReader sr = new StreamReader(VirtualStream)) 
     { 
      msg = sr.ReadToEnd(); 
     } 

     // modify string here 
     msg = msg.replace("\r\n",""); 

     while (msg.Contains(" <")) 
      msg = msg.Replace(" <", "<"); 

     VirtualStream outStream = new VirtualStream(); 
     StreamWriter sw = new StreamWriter(outStream, Encoding.Default); 
     sw.Write(msg); 
     sw.Flush(); 
     outStream.Seek(0, SeekOrigin.Begin); 

     pInMsg.BodyPart.Data = outStream; 
     pContext.ResourceTracker.AddResource(outStream); 
    } 

    return pInMsg; 
} 

Questo è il codice, ma come potete vedere sto rompendo il flusso quando faccio sr.ReadToEnd().

C'è un modo migliore per farlo?

risposta

2

Per il caso semplice del flusso di sola lettura non ricercabile, è possibile creare un flusso wrapper che sostituisce al volo secondo le necessità nel metodo Stream.Read (e possibilmente nel metodo Stream.ReadByte). Tuttavia, questi funzionano con i byte non elaborati, quindi potrebbe essere necessario tenere conto anche della codifica del flusso.

+0

Puoi forse elaborare con alcuni esempi di codice? Non ho esperienza con lo streaming .. thx –

4

Il fatto che si stiano utilizzando le classi Stream nel componente della pipeline non lo rende un componente della pipeline di streaming per-se come si è intuitivamente chiesto.

Il modo più appropriato è quello di dividere le responsabilità in due componenti:

  • In primo luogo, si crea un cliente System.IO.Stream di classe - che è una classe che avvolge il flusso in entrata originale ed espone un'interfaccia streaming. In questa classe, si elaborano efficacemente i byte quando vengono letti dal codice chiamante. Questa classe non dovrebbe avere alcuna dipendenza su BizTalk e dovresti essere in grado di creare un programma di test unitario di esempio per questa classe al di fuori di BizTalk.

Per il primo caso, si consiglia di selezionare uno dei several articleswith source code samples.

  • In secondo luogo, il componente della pipeline stessa, la cui unica responsabilità è di sostituire il flusso in entrata con un'istanza del flusso personalizzato. Questo è uno schema idiomatico che troverai in buoni componenti della pipeline. In particolare, durante l'esecuzione di Execute method, non si deve leggere lo stream originale in entrata. La lettura avverrà - automaticamente - da solo quando subentrerà lo Messaging Agent.

Il seguente frammento dovrebbe essere il codice sorgente canonica per un metodo Execute, salvo codice aggiuntivo per la gestione degli errori, naturalmente:

IBaseMessage IComponent.Execute(IPipelineContext pContext, IBaseMessage pInMsg) 
{ 
    // assign a new CustomStream to the incoming message 

    System.IO.Stream stream = pInMsg.BodyPart.GetOriginalDataStream(); 
    System.IO.Stream customStream = new CustomStream(stream); 

    // return the message for downstream pipeline components (further down in the pipeline) 

    pInMsg.BodyPart.Data = customStream; 
    pContext.ResourceTracker.AddResource(customStream); 

    return pInMsg; 
} 

Vedi? Nessuna lettura del metodo precedente. L'intera elaborazione dovrebbe avvenire durante le chiamate (ripetute) del metodo Read nella classe personalizzata Stream.

Come ho scritto nella risposta allo the following question, ti consiglio vivamente di dare un'occhiata a tutta la serie di post che lo Nic Barden ha svolto sullo sviluppo di componenti di streaming per pipeline.

0

Penso che il modo sarebbe mantenere un buffer di elaborazione e di elaborazione, quindi quando si arriva al nuovo contenuto scritto nel flusso lo si mantiene nel buffer in sospeso finché non si sa che non c'è altro da sostituire. Dopo aver sostituito o deciso che non c'è nulla da sostituire, spostare i dati dal buffer in sospeso al buffer fatto. Il metodo di lettura dovrebbe solo leggere dal buffer done, la scrittura dovrebbe scrivere solo nel buffer di elaborazione e flush sposta tutte le operazioni in sospeso a essere eseguite.

Non sicuro per la parte di lavaggio, mi sto pensando come farlo nel modo migliore in quanto ho bisogno di scrivere un flusso generico di sostituzione delle stringhe.

[modifica] Ci dispiace, rispose un post di 2 anni ... [/ modifica]

Problemi correlati