フラット ファイル逆アセンブラー パイプライン コンポーネントの拡張
次のサンプルは、UTF-7 でエンコードされたフラット ファイル ドキュメントを解析するカスタム逆アセンブラーを作成する方法を示しています。 UTF-7 ドキュメントを処理するために、コンポーネントは FFDasmComp クラスを継承し、 その GetDataReader メソッドをオーバーライドします。
using System;
using System.Text;
using System.IO;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.ParsingEngine;
using Microsoft.BizTalk.Component;
using System.Runtime.InteropServices;
namespace Microsoft.BizTalk.Test
{
/// <summary>
/// Implements FF disassembler which always uses UTF-7 encoding.
/// </summary>
[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
[ComponentCategory(CategoryTypes.CATID_DisassemblingParser)]
[ComponentCategory(CategoryTypes.CATID_Streamer)]
[Guid("A6E5F54F-7902-4e1a-84D8-5C7584F0ECF2")]
public class Utf7FFDasm :
FFDasmComp,
IBaseComponent
{
/// <summary>
/// Initializes a Utf7FFAsmDasm instance.
/// </summary>
public Utf7FFDasm()
{
}
/// <summary>
/// Name property
/// </summary>
public new string Name
{
get
{
return "UTF-7 FlatFile Disassembler";
}
}
/// <summary>
/// Version property
/// </summary>
public new string Version
{
get
{
return "1.0";
}
}
/// <summary>
/// Description property
/// </summary>
public new string Description
{
get
{
return "UTF-7 FlatFile Disassembler";
}
}
/// <summary>
/// Gets a data reader instance
/// </summary>
/// <param name="dataStream">Data stream</param>
/// <param name="dataEncoding">Data encoding</param>
/// <param name="detectEncodingFromByteOrderMarks">Detect encoding from a byte order mark</param>
/// <returns>IDataReader instance</returns>
protected override IDataReader GetDataReader(Stream dataStream, Encoding dataEncoding, bool detectEncodingFromByteOrderMarks)
{
// Delegate call to the base implementation passing fixed UTF-7 encoding
return base.GetDataReader(dataStream, Encoding.UTF7, false);
}
}
}
例
フラット ファイル インターチェンジのトランザクション処理用のカスタム逆アセンブラーを作成する方法を次に示します。 これは、入力されたインターチェンジ全体が完全に処理されるまで逆アセンブラー ドキュメントを生成しない点が、標準のフラット ファイル逆アセンブラーとは異なります。 このコンポーネント実装は FFDasmComp クラスを継承し、 GetNext メソッドをオーバーライドします。 GetNext メソッドの最初の呼び出しでは、インターチェンジ内のすべてのメッセージを処理し、それらを ArrayList に格納し、ArrayList から最初のメッセージを返します。 後続の呼び出しでは、 ArrayList から次のメッセージが返されます。
Note
次のコード例の GetNext() メソッドの実装では、インターチェンジ全体をメモリ内に保持するため、大規模なドキュメントの処理には適していません。 大規模なドキュメントにこの技法を使用すると、メモリ リソースを著しく消費し、パフォーマンスが低下したり、動作が不安定になったりする可能性があります。
using System;
using System.Collections;
using System.Runtime.InteropServices;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Component;
namespace Microsoft.BizTalk.Component
{
/// <summary>
/// Summary description for Class1.
/// </summary>
[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
[ComponentCategory(CategoryTypes.CATID_DisassemblingParser)]
[Guid("EB4714A8-FD97-43de-84E2-E011648F349B")]
public class TransactionalFFDasm :
FFDasmComp,
IBaseComponent,
IDisassemblerComponent
{
public TransactionalFFDasm()
{
}
#region IBaseComponent Members
public new string Description
{
get
{
return "Transactional Flat File Disassembler";
}
}
public new string Name
{
get
{
return "Transactional Flat File Disassembler";
}
}
public new string Version
{
get
{
return "1.0";
}
}
#endregion
#region IDisassemblerComponent Members
public new void Disassemble(IPipelineContext pContext, IBaseMessage pInMsg)
{
base.Disassemble(pContext, pInMsg);
}
public new IBaseMessage GetNext(IPipelineContext pContext)
{
// Check if don't need to stop collecting messages
if (currentMessage == 0)
{
messageInterchange = new ArrayList();
currentMessage = 0;
// Collect messages from the standard disassembler
IBaseMessage disassembledMessage = null;
while ((disassembledMessage = base.GetNext(pContext)) != null)
{
byte[] buffer = new byte[4096];
int count = 0;
// Create a new memory stream to contain the disassembled message.
MemoryStream messageStream = new MemoryStream();
// Get a stream pointer to the disassembled stream.
Stream disassembledStream = disassembledMessage.BodyPart.GetOriginalDataStream();
// Write the disassembled message to the memory stream
while (0 != (count == disassembledStream.Read(buffer, 0, 4096)))
{
messageStream.Write(buffer, 0, count);
} // end-while
// Rewind the stream to the beginning
messageStream.Seek(0, SeekOrigin.Begin);
// Replace the stream on the disassembled message with the memory stream.
disassembledMessage.BodyPart.data = messageStream;
// Add this message to the ArrayList of messages.
messageInterchange.Add(disassembledMessage);
} // end-while
// Check if no messages were collected, just return nothing
if (0 == messageInterchange.Count)
return null;
} // end-if
// Check if all collected messages are returned
if (currentMessage == messageInterchange.Count)
return null;
// Return the current collected message
return (IBaseMessage)messageInterchange[currentMessage++];
} // end-method GetNext()
#endregion
private ArrayList messageInterchange = null;
private int currentMessage = 0;
}
}