動的ポートを構成するための一般的な BizTalk アプリケーションを開発しようとしています。ポートごとにすべての構成設定を取得するオーケストレーションがあり、これらの設定をループしてポートを構成したいと考えています。設定は MSSQL に保持され、たとえば、2 つのプロパティは PortName と Address です。したがって、オーケストレーション内から、ポートを文字列変数 PortName で参照したいと思います。オーケストレーション内のすべてのポートのコレクションを取得する方法や、文字列変数を介してポートを参照する方法はありますかPort['MyPortName'](Microsoft.XLANGs.BaseTypes.Address) = "file://c:\test\out\%MessageId%.xml"
?
2 に答える
オーケストレーション内から動的論理送信ポートを動的に構成するには、設定を永続的なデータストア (データベースや構成ファイルなど) に保存し、実行時にそれらのプロパティを動的に割り当てる方法を実装する必要があります。
ただし、最初に、動的送信ポートを構成するときに何が起こっているかを理解する必要があります。
動的論理送信ポートを構成する方法
オーケストレーション内から動的論理送信ポートのプロパティを構成するには、次の 2 つの手順が必要です。
最初に、送信ポートでTransportTypeおよびターゲットAddressプロパティを指定する必要があります。これは通常、次のようなコードを使用してExpression Shapeで実行されます。
DynamicSendPort (Microsoft.XLANGs.BaseTypes.TransportType) = "ファイル"; DynamicSendPort(Microsoft.XLANGs.BaseTypes.Address) = "C:\Temp\Folder\%SourceFileName%";
次に、送信メッセージ自体のコンテキストで追加のトランスポート プロパティを指定する必要があります。実質的にすべての BizTalk アダプターには、メッセージング エンジンと XLANG/s オーケストレーション エンジン間の通信に使用される追加のプロパティがあります。たとえば、ReceivedFileNameコンテキスト プロパティを使用して、FILE アダプタが送信メッセージをターゲットの場所に保存するときに特定の名前を動的に設定します。これは、送信メッセージの作成の一環として、 Assignment Shape内で実行するのが最適です。
OutgoingMessage(FILE.ReceiveFileName) = "HardCodedFileName.xml"
ほとんどの構成プロパティは、名前空間プレフィックス (FILE など)、プロパティ名 (ReceiveFileName など)、および対応するプロパティに割り当てられる値を指定して、発信メッセージのコンテキストで指定する必要があることに気付くでしょう。
実際、すべてのコンテキスト プロパティは、well-known Microsoft.BizTalk.GlobalPropertySchemas.dll
アセンブリ内に存在するクラスです。これは、Visual Studio のオブジェクト エクスプローラーでこのアセンブリを検索することで確認できます。
動的論理送信ポートを構成するために必要なほとんどのコンテキスト プロパティは、この特定のアセンブリ内に存在しますが、すべてが存在するわけではありません。たとえば、MSMQ BizTalk アダプターは、別のアセンブリを使用してそのコンテキスト プロパティを格納します。明らかに、サードパーティ製またはカスタム アダプターには、追加のアセンブリも付属しています。
したがって、以下に説明するような柔軟なアプローチを使用して動的送信ポートにコンテキスト プロパティを設定するには、次の 4 つの情報が必要です。
- コンテキスト プロパティ クラスを含むアセンブリの完全修飾名。
- 名前空間のプレフィックス。
- プロパティ名。
- プロパティ値。
永続的なメディアへのポート設定の保存
次の .XSD スキーマは、ポート設定をシリアル化するための 1 つの可能な構造を示しています。
シリアル化されると、指定されたコンテキスト プロパティを SQL データベースまたは構成ファイルに非常に簡単に格納できます。たとえば、この投稿で例として使用されている設定は次のとおりです。
動的論理送信ポートを構成するための柔軟なアプローチ
シンプルなヘルパー ライブラリを使用すると、動的ポート構成のセットアップが非常に簡単になります。まず、シリアル化された設定を永続メディアから取得する必要があります。これは、WCF-SQL アダプターと単純なストアド プロシージャを使用して簡単に実現できます。
取得したプロパティは、厳密に型指定された C# オブジェクト グラフに逆シリアル化できます。このために、まず、次のコマンドライン ユーティリティを使用して、上記の ContextProperties スキーマの C# 表現を作成します。
xsd.exe /classes /language:cs /namespace:Helper.Schemas .\ContextProperties.xsd
これにより、次の方法で改善できる部分クラスが生成されます。
namespace Helper.Schemas
{
public partial class ContextProperties
{
public static ContextProperties Deserialize(string text)
{
using (MemoryStream stream = new MemoryStream())
{
byte[] buffer = Encoding.UTF8.GetBytes(text);
stream.Write(buffer, 0, buffer.Length);
stream.Seek(0, SeekOrigin.Begin);
return (ContextProperties)
Deserialize(
stream
, typeof(ContextProperties));
}
}
public static Object Deserialize(Stream stream, Type type)
{
XmlSerializer xmlSerializer = new XmlSerializer(type);
return xmlSerializer.Deserialize(stream);
}
}
}
次に、この構成を適用するには、コードから XLANG/s メッセージを作成し、逆シリアル化された ContextProperties オブジェクト グラフで指定されたコンテキスト プロパティ クラスの説明に基づいて、リフレクションを使用してコンテキスト プロパティを動的に設定する必要があります。
このために、動的変換に関するPaolo Salvatoriの一連の記事から借用した手法を使用します。これは、BizTalk XLANG/s エンジンによって内部的に使用されるカスタムBTXMessage 派生クラスを作成することから成ります。
namespace Helper.Schemas
{
using Microsoft.BizTalk.XLANGs.BTXEngine; // Found in Microsoft.XLANGs.BizTalk.Engine
using Microsoft.XLANGs.Core; // Found in Microsoft.XLANGs.Engine
[Serializable]
public sealed class CustomBTXMessage : BTXMessage
{
public CustomBTXMessage(string messageName, Context context)
: base(messageName, context)
{
context.RefMessage(this);
}
public void SetContextProperty(string assembly, string ns, string name, object value)
{
if (String.IsNullOrEmpty(ns))
ns = "Microsoft.XLANGs.BaseTypes";
if (String.IsNullOrEmpty(assembly))
assembly = "Microsoft.BizTalk.GlobalPropertySchemas";
StringBuilder assemblyQualifiedName = new StringBuilder();
assemblyQualifiedName.AppendFormat("{0}.{1}, {2}", ns, name, assembly);
Type type = Type.GetType(assemblyQualifiedName.ToString(), true, true);
SetContextProperty(type, value);
}
internal void SetContextProperty(string property, object value)
{
int index = property.IndexOf('.');
if (index != -1)
SetContextProperty(String.Empty, property.Substring(0, index), property.Substring(index + 1), value);
else
SetContextProperty(String.Empty, String.Empty, property, value);
}
}
}
さて、パズルの最後のピースは、オーケストレーション内からこのカスタム クラスを利用する方法です。これは、次のヘルパー コードを使用して、 Assignment Shapeで簡単に実行できます。
namespace Helper.Schemas
{
using Microsoft.XLANGs.BaseTypes;
using Microsoft.XLANGs.Core; // Found in Microsoft.XLANGs.Engine
public static class Message
{
public static XLANGMessage SetContext(XLANGMessage message, ContextProperties properties)
{
try
{
// create a new XLANGMessage
CustomBTXMessage customBTXMessage = new CustomBTXMessage(message.Name, Service.RootService.XlangStore.OwningContext);
// add parts of the original message to it
for (int index = 0; index < message.Count; index++)
customBTXMessage.AddPart(message[index]);
// set the specified context properties
foreach (ContextPropertiesContextProperty property in properties.ContextProperty)
customBTXMessage.SetContextProperty(property.assembly, property.@namespace, property.name, property.Value);
return customBTXMessage.GetMessageWrapperForUserCode();
}
finally
{
message.Dispose();
}
}
}
}
以下に示すコードのように、割り当て形状内でこの静的メソッドを使用できます。ここでOutboundMessage
、コンテキストを設定するメッセージを表します。
OutboundMessage = Helper.Schemas.Message.SetContext(OutboundMessage, contextProperties);
そもそも、オーケストレーションを使用してこのような構成変更を試みるべきではありません。技術的には、実行しようとしていることを実行することは可能ですが、実践として、ビジネスプロセスと管理を混同しないでください。
このようなことを行う最良の方法は、通常のスクリプトまたはPowerShellを作成することです。
質問に答えるために、ExplorerOMのBtsOrchestrationクラスから必要なデータを取得できます http://msdn.microsoft.com/en-us/library/microsoft.biztalk.explorerom.btsorchestration_members(v=bts.20)