Ссылка на порт в оркестровке через строковую переменную

Я пытаюсь разработать универсальное приложение BizTalk для настройки динамических портов. У меня есть оркестровка, которая извлекает все параметры конфигурации для каждого порта, и я хочу просмотреть эти параметры и настроить порты. Настройки хранятся в MSSQL, и, например, два свойства — это PortName и Address. Поэтому из оркестровки я хотел бы сослаться на порт с помощью строковой переменной PortName. Итак, есть ли способ получить коллекцию всех портов в оркестровке или сослаться на порт через строковую переменную, т.е. Port['MyPortName'](Microsoft.XLANGs.BaseTypes.Address) = "file://c:\test\out\%MessageId%.xml" Спасибо.


person RedEyedMonster    schedule 21.05.2012    source источник
comment
Я понимаю, что не ответил строго на ваш вопрос, а скорее показал динамическое применение настроек порта в контексте исходящего сообщения. Это вторая часть уравнения. Я попытаюсь выяснить, как ссылаться на порт в виде строки и улучшить свой ответ ниже.   -  person Maxime Labelle    schedule 05.07.2012


Ответы (2)


Во-первых, вы не должны пытаться вносить подобные изменения в конфигурацию с помощью Orchestration. Технически возможно сделать то, что вы пытаетесь сделать, но на практике вы не должны смешивать свой бизнес-процесс с администрированием.

Лучший способ сделать это — написать несколько обычных сценариев или использовать PowerShell.

Чтобы ответить на ваш вопрос, вы можете получить нужные данные из класса BtsOrchestration в ExplorerOM http://msdn.microsoft.com/en-us/library/microsoft.biztalk.explorerom.btsorchestration_members%28v=bts.20%29

person Community    schedule 22.05.2012
comment
Спасибо за информацию, к сожалению, ссылка, которую вы прислали, не работает. Однако я уже рассматриваю ExplorerOM как возможное решение. Не могли бы вы объяснить, почему мне не следует настраивать динамические порты с помощью оркестровки? Обычно мы извлекаем такие параметры из SSO во время выполнения, однако, если их нужно изменить, нам нужно перезапустить экземпляр хоста, тогда как извлечение их из SQL означает, что их можно перенастроить в любое время. Сейчас я пытаюсь сделать процесс более общим, чтобы его можно было вызывать из любого приложения BT. - person RedEyedMonster; 22.05.2012

Для динамической настройки динамических логических портов отправки из оркестровки необходимо сохранить настройки в постоянном хранилище данных (например, в базе данных или файле конфигурации) и реализовать способ динамического назначения этих свойств во время выполнения.

Но сначала нам нужно понять, что происходит при настройке порта динамической отправки.

Как настроить динамический логический порт отправки

Настройка свойств динамического логического порта отправки внутри оркестровки включает два шага:

  • Во-первых, TransportType и укажите адрес свойства должны быть указаны для порта отправки. Обычно это делается в Форме выражения с кодом, подобным этому:

    DynamicSendPort(Microsoft.XLANGs.BaseTypes.TransportType) = "ФАЙЛ"; DynamicSendPort(Microsoft.XLANGs.BaseTypes.Address) = "C:\Temp\Folder\%SourceFileName%";

  • Во-вторых, любые дополнительные свойства транспорта должны быть указаны в контексте самого исходящего сообщения. Практически все адаптеры BizTalk имеют дополнительные свойства которые используются для связи между механизмом обмена сообщениями и механизмом оркестровки XLANG/s. Например, ReceivedFileName свойство контекста используется для динамической установки определенного имени, когда адаптер FILE будет сохранять исходящее сообщение в его целевом местоположении. Лучше всего это делать внутри фигуры назначения, как часть построения исходящего сообщения:

    OutgoingMessage(FILE.ReceiveFileName) = "HardCodedFileName.xml"

Вы заметите, что большинство свойств конфигурации необходимо указывать в контексте исходящих сообщений, указывая префикс пространства имен (например, FILE), имя свойства (например, ReceiveFileName) и, очевидно, значение, которое присваивается соответствующему свойству.

На самом деле все свойства контекста — это классы, живущие внутри хорошо известной сборки Microsoft.BizTalk.GlobalPropertySchemas.dll. Это подтверждается поиском этой сборки в обозревателе объектов Visual Studio.

FILE.ReceivedFileName в Microsoft.BizTalk.GlobalPropertySchemas.dll

Несмотря на то, что большинство свойств контекста, необходимых для настройки динамических логических портов отправки, находятся внутри этой конкретной сборки, не все из них существуют. Например, адаптер MSMQ BizTalk использует отдельную сборку для хранения своих свойств контекста. Очевидно, что сторонние или пользовательские адаптеры также поставляются с дополнительными сборками.

Таким образом, для настройки свойства контекста в порту динамической отправки с использованием гибкого подхода, подобного описанному ниже, необходимы четыре элемента информации:

  • Полное имя сборки, содержащей классы свойств контекста.
  • Префикс пространства имен.
  • Имя свойства.
  • Стоимость свойства.

Сохранение настроек порта на постоянном носителе

Следующая схема .XSD иллюстрирует одну из возможных структур для сериализации параметров порта.

Определение XML-схемы ContextProperties

После сериализации указанные свойства контекста можно очень легко сохранить в базе данных SQL или в файле конфигурации. Например, вот настройки, используемые в качестве примера в этом посте:

Пример настроек ContextProperties

Гибкий подход к настройке динамических логических портов отправки

С помощью простой вспомогательной библиотеки настроить динамическую конфигурацию порта очень просто. Во-первых, вы должны получить сериализованные настройки с постоянного носителя. Этого легко добиться с помощью адаптера WCF-SQL и простой хранимой процедуры.

После извлечения эти свойства можно десериализовать в строго типизированный граф объектов C#. Для этого сначала создайте C#-представление схемы ContextProperties, показанной выше, с помощью следующей утилиты командной строки:

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.

Для этого я использую метод, заимствованный из серии статей Паоло Сальватори относительно динамических преобразований, заключающихся в создании собственного 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);
        }

    }
}

Теперь последняя часть головоломки — как использовать этот пользовательский класс внутри Orchestration. Это легко сделать в форме назначения с помощью следующего вспомогательного кода:

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);
person Community    schedule 04.07.2012