通过字符串变量引用编排中的端口
-
12-12-2019 - |
题
我正在尝试开发用于配置动态端口的通用BizTalk应用程序。我有一个编排,它拉回每个端口的所有配置设置,我想循环执行这些设置并配置端口。这些设置保存在MSSQL中,例如,其中两个属性是PortName和Address。因此,从业务流程中,我想通过字符串变量PortName引用端口。那么有没有办法通过字符串变量即获取编排中所有端口的集合或引用端口 Port['MyPortName'](Microsoft.XLANGs.BaseTypes.Address) = "file://c:\test\out\%MessageId%.xml"
谢谢
解决方案
首先,您不应该尝试使用编排来进行这样的配置更改。从技术上讲,做你试图做的事情是可行的,但作为一种实践,你不应该把你的业务流程和管理混为一谈。
做这些事情的最好方法是编写一些正常的脚本或PowerShell。
要回答你的问题,你可以从ExplorerOM中的BtsOrchestration类中获取你想要的数据 http://msdn.microsoft.com/en-us/library/microsoft.biztalk.explorerom.btsorchestration_members(v=bts.20)
其他提示
为了从业务流程中动态配置动态逻辑发送端口,必须将设置存储到持久数据存储中(例如个数据库或配置文件)并实现在运行时动态分配那些属性的方式。
但首先,我们需要了解在配置动态发送端口时发生了什么。
如何配置动态逻辑发送端口
配置动态逻辑发送端口的属性 在业务流程中,包括两个步骤:
首先, 运输类型 和目标 地址 必须在发送端口上指定属性。这通常是在一个 表情形状 用类似这样的代码:
DynamicSendPort(微软。XLANGs。基本类型。TransportType)="文件";DynamicSendPort(微软。XLANGs。基本类型。地址)="C: emp\Folder\%SourceFileName%";
其次,必须在传出邮件本身的上下文中指定任何其他传输属性。几乎所有的BizTalk适配器都有 其他属性 用于消息传递引擎和XLANG/S编排引擎之间的通信。例如, 接收文件名 context属性用于动态设置文件适配器何时将传出消息保存在其目标位置的特定名称。这是最好的内部执行 分配形状, ,作为构造传出消息的一部分:
OutgoingMessage(文件.ReceiveFileName)="HardCodedFileName。xml"
您会注意到,大多数配置属性必须在传出消息的上下文中指定,指定命名空间前缀(例如文件),属性名称(例如ReceiveFileName)和,显然,被分配到相应的属性的值。
事实上,所有的上下文属性都是生活在 知名的 Microsoft.BizTalk.GlobalPropertySchemas.dll
组装。通过在Visual Studio的对象资源管理器中查找此程序集来确认这一点。
即使配置动态逻辑发送端口所必需的大多数上下文属性都存在于此特定程序集中,但并非所有上下文属性都存在。例如,MSMQ BizTalk适配器使用单独的程序集来存储其上下文属性。显然,第三方或自定义适配器也附带additionnal组件。
因此,为了使用如下所述的灵活方法在动态发送端口上设置上下文属性,需要四条信息:
- 包含上下文属性类的程序集的完全限定名称。
- 命名空间前缀。
- 属性名称。
- 的属性值。
将端口设置存储在持久介质中
以下。XSD架构说明了串行化端口设置的一种可能结构。
一旦序列化,指定的上下文属性就可以很容易地存储在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);
}
}
}
其次,应用此配置涉及根据反序列化ContextProperties对象图中指定的上下文属性类的描述,从代码创建XLANG/s消息并使用反射动态设置上下文属性。
为此,我使用借用的技术 保罗*萨尔瓦托里系列文章 关于动态变换, ,其中包括创建自定义 BTXMessage-派生类,由BizTalk XLANG/s引擎内部使用。
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);
}
}
}
现在,最后一个难题是如何在业务流程中使用这个自定义类。这很容易在一个 分配形状 使用以下帮助程序代码:
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);