WCF сервис в виде Activity

Создание Workflow, работающего в составе сервиса технологии WCF - это дело обычное, почти рутина. Однако можно ли создать WCF сервис в виде Activity и запустить его из Workflow? Ну, а чтобы ему не было "одиноко" напишем для сервиса и клиент в виде Activity :). Оформим эту пару компонентов в виде dll библиотеки с тем, чтобы их можно было развернуть как в Visual Studio, так и в другой среде разработки или моделирования. Но для чего могут потребоваться такие Activity? По мнению автора эти компоненты позволяют быстро создавать и моделировать работу систем. Простой пример такого применения приведен в статье.
Проект MS Visual Studio 2012, содержащий библиотеку и пример ее использования, можно загрузить бесплатно.
1. Реализация WCF службы в виде Activity.
Приведенная ниже WCF служба реализована полность в виде кода. Однако это вовсе не обязательно, может быть использован и конфигурационный файл. В качестве настраиваемого параметра служит hhtp адрес службы. Привязки и контракты в данном примере не настраиваемые. Все определения даны в терминах книги "Основы Windows Communication Foundation" авторов: Стив Резник, Ричард Крейн, Крис Боуэн, на которую я хочу сослаться.
Code

/*  10.07.2013

    Пример реализации сервиса WCF в виде Activity для Workflow.

    An example of the WCF service in the form of Activity Workflow.

*/

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Activities;

using System.ServiceModel;

using System.ServiceModel.Description;

using System.ComponentModel;

namespace ActivityLibrary

{

    public sealed class WcfService : CodeActivity

    {

        [RequiredArgument]

        [DefaultValue(null)]

        public InArgument<string> uriService { get; set; }

        private string uri = string.Empty;

        protected override void Execute(CodeActivityContext context)

        {

            try

            {

                uri = context.GetValue(uriService);

                // Check uri

                if (String.IsNullOrEmpty(uri.ToString())) throw new ArgumentNullException("Value", "Uri the Service is null or empty");

                // Create ServiceHost

                ServiceHost serviceHost = new ServiceHost(typeof(HelloService), new Uri(uri));              

                // Add Endpoint

                serviceHost.AddServiceEndpoint(typeof(IHelloService), new BasicHttpBinding(), "");

                // Create Behavior

                ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();

                behavior.HttpGetEnabled = true;

                // Add Behavior

                serviceHost.Description.Behaviors.Add(behavior);

                serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");               

                // Open Host

                serviceHost.Open();

                Console.WriteLine("Service started at {0}\r\n", serviceHost.BaseAddresses[0]);

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex);

            }

        }

    }

}

2. Реализация WCF клиента в виде Activity.
Чтобы не затемнять деталями суть дела, клиент создан максимально простым. Входным параметром для него служит адрес службы.
Code

/*  10.07.2013.

    Пример реализации клиента для WCF Activity, в виде Activity.

    An example of the implementation of a client for WCF Activity, in the form of Activity.

*/

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Activities;

using System.ServiceModel;

using System.ComponentModel;

using System.Threading.Tasks;

using System.Windows;

namespace ActivityLibrary

{

    public sealed class ClientWcfService : CodeActivity

    {

        [RequiredArgument]

        [DefaultValue(null)]

        public InArgument<string> uriService { get; set; }

        private string uri = string.Empty;

        protected override void Execute(CodeActivityContext context)

        {

            try

            {

                uri = context.GetValue(uriService);

                if (String.IsNullOrEmpty(uri.ToString())) throw new ArgumentNullException("Value", "Uri client is null or empty");

                ChannelFactory<IHelloService> myChannelFactory =

                    new ChannelFactory<IHelloService>(

                    new BasicHttpBinding(),

                    new EndpointAddress(uri)

                    );

                IHelloService wcfClient = myChannelFactory.CreateChannel();

                string message = wcfClient.DoClient();

                Console.WriteLine("Client print:{0}", message);

            }

            catch (Exception ex) { Console.WriteLine(ex); }        

        }

    }

}

3. Применение компонентов в рабочем потоке.
Для демонстрации работы компонентов создадим Workflow Console Application, далее, перенесем на форму из панели Toolbox компоненты Flowchart, WcfService, в цикл While поместим ClientWcfService, вот и все, проект готов :).


В цикл While так же помещена переменная цикла и небольшая задержка. Конечно многократный вызов сервиса лучше выполнять методом DoClient() непосредственно в клиенте, и этому ничего не мешает, однако, так нагляднее. Можно усложнить задачу и создать, например, несколько параллельных потоков, в каждом из которых организовать обращение к сервису.



Microsoft Visual Studio 2012 проект приложения можно свободно загрузить.
Евгений Вересов.
20.07.2015 года.