Biztalk 通过字符串变量引用业务流程中的端口

Biztalk 通过字符串变量引用业务流程中的端口,biztalk,biztalk-2010,orchestration,Biztalk,Biztalk 2010,Orchestration,我正在尝试开发一个用于配置动态端口的通用BizTalk应用程序。我有一个业务流程,它可以收回每个端口的所有配置设置,我想循环这些设置并配置端口。这些设置保存在MSSQL中,例如,其中两个属性是PortName和Address。因此,在业务流程中,我希望通过字符串变量PortName引用端口。因此,是否有某种方法可以获取业务流程中所有端口的集合或通过字符串变量引用端口,即port['MyPortName'](Microsoft.XLANGs.BaseTypes.Address)=“file://c

我正在尝试开发一个用于配置动态端口的通用BizTalk应用程序。我有一个业务流程,它可以收回每个端口的所有配置设置,我想循环这些设置并配置端口。这些设置保存在MSSQL中,例如,其中两个属性是PortName和Address。因此,在业务流程中,我希望通过字符串变量PortName引用端口。因此,是否有某种方法可以获取业务流程中所有端口的集合或通过字符串变量引用端口,即
port['MyPortName'](Microsoft.XLANGs.BaseTypes.Address)=“file://c:\test\out\%MessageId%.xml”
谢谢首先,您不应该尝试使用业务流程进行类似的配置更改。从技术上讲,做你想做的事情是可行的,但作为一种实践,你不应该把你的业务流程和管理混为一谈

最好的方法是编写一些普通脚本或PowerShell

要回答您的问题,您可以从ExplorerOM中的BtsOrchestration类获取所需的数据

首先,您不应该尝试使用编排进行这样的配置更改。从技术上讲,做你想做的事情是可行的,但作为一种实践,你不应该把你的业务流程和管理混为一谈

最好的方法是编写一些普通脚本或PowerShell

要回答您的问题,您可以从ExplorerOM中的BtsOrchestration类获取所需的数据

为了从业务流程中动态配置动态逻辑发送端口,必须将设置存储到持久数据存储(例如数据库或配置文件)中,并实现在运行时动态分配这些属性的方法

但首先,我们需要了解在配置动态发送端口时发生了什么

如何配置动态逻辑发送端口

从编排内部开始包括两个步骤:

  • 首先,必须在发送端口上指定和目标属性。这通常在表达式形状中完成,代码类似于:

    DynamicSendPort(Microsoft.XLANGs.BaseTypes.TransportType)=“文件”; DynamicSendPort(Microsoft.XLANGs.BaseTypes.Address)=“C:\Temp\Folder\%SourceFileName%”

  • 其次,必须在传出消息本身的上下文中指定任何其他传输属性。实际上,所有BizTalk适配器都具有用于消息传递引擎和XLANG/s编排引擎之间通信的适配器。例如,context属性用于动态设置文件适配器在其目标位置保存传出消息时的特定名称。这最好在分配形状内执行,作为构造传出消息的一部分:

    OutgoingMessage(FILE.ReceiveFileName)=“HardCodedFileName.xml”

您会注意到,大多数配置属性都必须在传出消息的上下文中指定,指定名称空间前缀(例如FILE)、属性名称(例如ReceiveFileName)以及分配给相应属性的值

事实上,所有上下文属性都是位于众所周知的
Microsoft.BizTalk.GlobalPropertySchemas.dll
程序集中的类。这可以通过在Visual Studio的对象资源管理器中查找此程序集来确认

即使配置动态逻辑发送端口所需的大多数上下文属性都存在于该特定程序集中,但并非所有上下文属性都存在于该程序集中。例如,MSMQ BizTalk适配器使用单独的程序集存储其上下文属性。显然,第三方或自定义适配器也附带了附加的程序集

因此,为了使用如下所述的灵活方法在动态发送端口上设置上下文属性,需要四条信息:

  • 包含上下文属性类的程序集的完全限定名
  • 名称空间前缀
  • 属性名
  • 属性值
在持久介质中存储端口设置

下面的.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);
        }
    }
}
其次,应用此配置涉及从代码创建XLANG/s消息,并根据反序列化ContextProperties对象图中指定的上下文属性类的描述,使用反射动态设置上下文属性

为此,我使用了从的一系列文章中借用的技术,其中包括创建一个自定义派生类,该类由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 = Helper.Schemas.Message.SetContext(OutboundMessage, contextProperties);