FileRead Windows Workflow Activity

Статья описывает Windows Workflow Activity FileRead. Activity разработана на языке C#. Activity получает от клиента имя файла произвольного типа, читает его, формирует байтовый массив и передает клиенту посредством Web Service WCF. Клиент получает и отображает байтовый массив, записывает точную копию считанного файла на локальный диск с новым именем. Представлен рабочий проект MS Visual Studio 2010 WCF + WorkFlow, в котором применяется описываемое Activity. В состав проекта входят WorkFlow, библиотека входных и выходных классов, Windows Form клиент запрашивающий, получающий и записывающий данные в файл. Клиент отображает полученный с сервера байтовый массив.
1. Входные данные Activity FileRead.
Единственым входным аргументом Activity служит имя файла :
[RequiredArgument]
public InArgument<string> fileName { get; set; }
2. Выходные данные Activity FileRead.
Выходные аргументы для Activity находяться в класса OutputArguments и состоят из двух свойств.
namespace ClassLibrary
{
    public class OutputArguments
    {
        public byte[]   data   { get; set; }
        public string   error  { get; set; }
    }
}
3. Исходный текст Activity FileRead.
Класс реализующий Activity FileRead создан асинхронным, содержащим два метода:
  • BeginExecute;
  • EndExecute.
Как видно из приведенного ниже текста, чтение файла начинается в методе BeginExecute, затем работа Activity приостаналивается и завершается процесс в методе EndExecute.
/* 28.07.2012 Activity для асинхронного чтения файла.
   Входной параметр - имя файла.
   Выходными параметрами являются массив байтов и строка ошибки.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.IO;
using ClassLibrary;

namespace ActivityLibrary
{
    public sealed class ReadFile : AsyncCodeActivity
    {
        [RequiredArgument]
        public InArgument<string> fileName { get; set; }

        [RequiredArgument]
        public OutArgument<OutputArguments> OutputArguments { get; set; }

        private byte[] buff                 = null;
        private FileStream file             = null;
        private String FileName             = String.Empty;
        private OutputArguments outData     = null;

        protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
        {
            try
            {
                // Check name file
                if (String.IsNullOrEmpty(fileName.Get(context))) throw new ArgumentNullException("Value", "File Name is null");
                // Get name file
                FileName = Path.GetFullPath(fileName.Get(context));
                // Check file
                if (!File.Exists(FileName)) throw new ArgumentNullException("Value", "Not Exists File");
                // Open file
                file = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                context.UserState = file;
                // Size file
                int length = (int)file.Length;
                buff = new byte[length];
                //Start read file
                return file.BeginRead(buff, 0, length, callback, state);
            }
            catch (Exception ex)
            {
                outData.error = ex.ToString();
                Console.WriteLine(ex.Message);
                return null;
            }
        }

        protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
        {           
            try
            {
               file = (FileStream)context.UserState;
               file.EndRead(result);
               // Create output argument
               outData = new OutputArguments();
               outData.data = buff;
            }
            catch (Exception ex)
            {
                outData.error = ex.ToString();
                Console.WriteLine(ex.Message);
            }
            finally
            {
                file.Close();
            }
            OutputArguments.Set(context, outData);
        }
    }
}
4. Клиент для Activity FileRead.
Ниже приведен пример клиента, который организует запрос к серверу, принимает, отображает и сохраняет данные в файле.
/* 28.07.2012
  Клиент для проверки Activity ReadFile.
  1. Обеспечивает диалог для выбора имени файла.
  2. Передает имя файла Activity.
  3. Принимает byte[] и отображает в textBox в виде списка байтов.
  4. Записывает массив на диск в виде файла.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ClassLibrary;
using System.IO;

namespace ClientReadFileAsyncActivity
{
    public partial class Form1 : Form
    {
        OutputArguments outData     = null;
        OpenFileDialog dialog       = null;
        string ext                  = String.Empty;
        string fileName             = String.Empty;
        string new_name             = String.Empty;

        ServiceReference.ServiceClient client;
        public Form1()
        {
            InitializeComponent();
            outData = new OutputArguments();
            client  = new ServiceReference.ServiceClient();
        }

        // Write file
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (String.IsNullOrEmpty(textBox2.Text)) throw new ArgumentNullException("Value", "Name file empty");
                if (String.IsNullOrEmpty(textBox3.Text)) throw new ArgumentNullException("Value", "New name file is empty");
                outData = client.GetData(textBox2.Text);
                string outStr = null;
                
                if (outData.error == null)
                {  
                    // Output byte
                    foreach(byte item in outData.data) outStr += item.ToString() + " ";
                    textBox1.Text = outStr;
                    // Write file
                    File.WriteAllBytes(textBox3.Text, outData.data);
                }
                else
                {
                    MessageBox.Show(outData.error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Error",MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        // Open dialog and select file
        private void button2_Click(object sender, EventArgs e)
        {
            // Open Dialog
            dialog = new OpenFileDialog();
            dialog.InitialDirectory = "G:\\";
            dialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            dialog.FilterIndex = 2;
            dialog.RestoreDirectory = true;
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                //Create new name
                textBox2.Text = dialog.FileName;
                ext = dialog.FileName.Substring(dialog.FileName.IndexOf(".") + 1);
                fileName = dialog.FileName.Substring(dialog.FileName.IndexOf("\\") + 1);
                new_name = fileName.Substring(0, fileName.IndexOf(".")) + "_new" + "." + ext;
                textBox3.Text = @"G:\" + new_name;
            }
        }
    }
}

Visual Studio 2010 проект содержащий: Activity, Workflow, Windows Form клиент можно загрузить.
Евгений Вересов.
28.07.2012 года.