protected override void ReadFile(string file, Stream stream, OperationInterop interop)
        {
            if (UseEncoding1251 && UseEncoding866)
                throw new InvalidOperationException("Установлены взаимоисключающие параметры кодировки");

            DbfReader dbfReader = new DbfReader();
            try
            {
                dbfReader.Open(stream, UseEncoding1251 ? Windows1251 : UseEncoding866 ? CP866 : null);

                Columns = dbfReader.Columns;
                Data = new List<Dictionary<string, object>>();

                Dictionary<string, object> record = null;
                while ((record = dbfReader.ReadRecord()) != null)
                {
                    Data.Add(record);
                }
            }
            finally
            {
                try
                {
                    dbfReader.Close();
                }
                catch { }
            }
        }
        /// <summary>
        /// Сформатировать данные в поток
        /// </summary>
        /// <param name="data">Коллекция массивов значений</param>
        /// <exception cref="InvalidOperationException">Не установлен выходной поток</exception>
        internal void Format(IEnumerable<object[]> data, OperationInterop interop)
        {
            if (Streams.Count == 0)
            {
                throw new InvalidOperationException("Не установлен выходной поток");
            }

            OnBeforeFormatting();
            CustomFormat(data, interop);
            OnAfterFormatting();
        }
        internal void ReadFiles(OperationInterop interop)
        {
            if (Streams.Count == 0)
            {
                throw new InvalidOperationException("Не установлен входной файл");
            }

            OnBeforeFileReading();
            foreach (var stream in Streams)
            {
                // >>>
                interop.SetStatusText("Чтение файла " + stream.Key);
                interop.ThrowIfCancellationRequested();
                // <<<
                ReadFile(stream.Key, stream.Value, interop);
            }
            OnAfterFileReading();
        }
 protected abstract void ReadFile(string file, Stream stream, OperationInterop interop);
 protected abstract void ExecuteExchange(OperationInterop interop);
 public void Execute(OperationInterop interop)
 {
     ExecuteExchange(interop);
 }
        /// <summary>
        /// Запуск последовательно
        /// </summary>
        /// <param name="operation"></param>
        /// <returns></returns>
        private OperationObject RunSerial(ICompositeOperation operation)
        {
            var operations = operation.GetOperations();
            if (operations == null || operations.Length == 0)
            {
                throw new ArgumentException("No any operation to run ", "consequentOperations");
            }

            // Инициализация
            int n = operations.Length;

            var tokenSource = new CancellationTokenSource();
            var commonState = new InteropState();

            var mockOperationObj = new OperationObject { OperationId = GetNewIndex() };
            var mockInterop = new OperationInterop(mockOperationObj, tokenSource.Token, commonState);

            OperationObject[] conseqOperationObjects = new OperationObject[n];

            // Создание объектов представления операций
            for (int i = 0; i < n; ++i)
            {
                conseqOperationObjects[i] = new OperationObject
                {
                    Parent = mockOperationObj
                };
                mockOperationObj.Children.Add(conseqOperationObjects[i]);
            }

            Task chainEnd = null;
            Task firstTask = null;
            bool finalSet = false;

            // Создание цепочки выполнения
            for (int i = 0; i < n; ++i)
            {
                // --> Переменные для замыкания
                var j = i;
                var thisOperation = operations[i];
                var thisOperationObj = conseqOperationObjects[i];
                var thisInterop = new OperationInterop(thisOperationObj, tokenSource.Token, commonState);
                // <--

                thisOperationObj.OperationId = GetNewIndex();
                thisOperationObj.Name = thisOperation.OperationInfo.Name;

                // Chain :: Выполнение операции
                if (chainEnd == null)
                {
                    // Первая операция
                    chainEnd = new Task(() =>
                    {
                        mockOperationObj.Status = OperationStatus.Running;
                        operation.OnChainStart(mockInterop);
                        thisOperation.Execute(thisInterop);
                    },
                    tokenSource.Token);
                    firstTask = chainEnd;
                }
                else
                {
                    // Цепляем следующие
                    chainEnd = chainEnd.ContinueWith((_, __) =>
                    {
                        tokenSource.Token.ThrowIfCancellationRequested();

                        thisOperation.Execute(thisInterop);
                    },
                    null, tokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current);
                }

                // Chain :: Обработка законченной операции
                chainEnd = chainEnd.ContinueWith(et =>
                {
                    thisOperation.Dispose();

                    // Установка статуса собственной операции
                    thisOperationObj.Status = et.Status.ToOperationStatus();

                    // Установка статуса главной репрезентативной операции
                    if (!finalSet)
                    {
                        if (et.Status != TaskStatus.RanToCompletion)
                        {
                            // Любая операция завершилась неуспешно
                            mockOperationObj.Status = et.Status.ToOperationStatus();

                            thisOperationObj.Exception = et.Exception;
                            mockOperationObj.Exception = et.Exception;

                            if (!IsBeingWatched(mockOperationObj))
                            {
                                Notifier.Notify("Операция #" + mockOperationObj.OperationId, "Операция не завершена", null);
                            }

                            tokenSource.Cancel();
                            finalSet = true;
                        }
                        else if (j == n - 1)
                        {
                            // Последняя операция завершилась успешно
                            mockOperationObj.Status = OperationStatus.RanToCompletion;
                            mockOperationObj.Progress = 100;

                            if (!IsBeingWatched(mockOperationObj))
                            {
                                Notifier.Notify("Операция #" + mockOperationObj.OperationId, "Операция завершена", null);
                            }

                            tokenSource.Cancel();
                            finalSet = true;
                        }
                    }

                    if (j < n - 1)
                    {
                        // Установка прогресса главной репрезентативной операции
                        UpdateMockOperationProgress(mockOperationObj, n, j + 1);
                    }
                });

                thisOperationObj.Status = OperationStatus.Created;
            }

            chainEnd.ContinueWith(t =>
            {
                operation.OnChainEnded();
                operation.Dispose();
            });

            // Обработка и запуск выполнения цепочки
            mockOperationObj.Status = OperationStatus.Created;
            mockOperationObj.Added = DateTime.Now;
            mockOperationObj.Name = operation.OperationInfo.Name;

            AddOperation(mockOperationObj);
            AddUnit(mockOperationObj.OperationId, new OperationUnit { CancellationTokenSource = tokenSource, ChainEndTask = chainEnd }, operations);

            firstTask.Start();

            return mockOperationObj;
        }
        /// <summary>
        /// Запуск параллельно
        /// </summary>
        /// <param name="operation"></param>
        /// <returns></returns>
        private OperationObject RunParallel(ICompositeOperation operation)
        {
            var operations = operation.GetOperations();
            if (operations == null || operations.Length == 0)
            {
                throw new ArgumentException("No any operation to run ", "consequentOperations");
            }

            // Инициализация
            int n = operations.Length;

            var tokenSource = new CancellationTokenSource();
            var commonState = new InteropState();

            var mockOperationObj = new OperationObject { OperationId = GetNewIndex() };
            var mockInterop = new OperationInterop(mockOperationObj, tokenSource.Token, commonState);

            OperationObject[] parallelOperationObjects = new OperationObject[n];

            // Создание объектов представления операций
            for (int i = 0; i < n; ++i)
            {
                parallelOperationObjects[i] = new OperationObject
                {
                    Parent = mockOperationObj
                };
                mockOperationObj.Children.Add(parallelOperationObjects[i]);
            }

            List<Task> tasks = new List<Task>();

            int finishedCount = 0;
            bool totalSuccess = true;
            bool canceled = false;

            // Создание цепочки выполнения
            for (int i = 0; i < n; ++i)
            {
                // текущая задача
                Task task = null;

                // --> Переменные для замыкания
                var j = i;
                var thisOperation = operations[i];
                var thisOperationObj = parallelOperationObjects[i];
                var thisInterop = new OperationInterop(thisOperationObj, tokenSource.Token, commonState);
                // <--

                thisOperationObj.OperationId = GetNewIndex();
                thisOperationObj.Name = thisOperation.OperationInfo.Name;

                // Запуск операции
                task = new Task(() =>
                {
                    thisOperationObj.Status = OperationStatus.Running;
                    thisOperation.Execute(thisInterop);
                },
                tokenSource.Token);

                // Обработка законченной операции
                task.ContinueWith(et =>
                {
                    thisOperation.Dispose();

                    finishedCount++;

                    // Установка статуса собственной операции
                    thisOperationObj.Status = et.Status.ToOperationStatus();
                    if (et.Status != TaskStatus.RanToCompletion)
                    {
                        thisOperationObj.Exception = et.Exception;
                        totalSuccess = false;
                        if (et.Status == TaskStatus.Canceled)
                        {
                            canceled = true;
                            tokenSource.Cancel();
                        }
                    }

                    // Установка прогресса главной репрезентативной операции
                    UpdateMockOperationProgress(mockOperationObj, n, finishedCount);

                    // завершились все задачи
                    // Установка статуса главной репрезентативной операции
                    if (finishedCount == n)
                    {
                        if (totalSuccess)
                        {
                            // Последняя операция завершилась успешно
                            mockOperationObj.Status = OperationStatus.RanToCompletion;
                            mockOperationObj.Progress = 100;

                            if (!IsBeingWatched(mockOperationObj))
                            {
                                Notifier.Notify("Операция #" + mockOperationObj.OperationId, "Операция завершена", null);
                            }
                        }
                        else
                        {
                            mockOperationObj.Status = canceled ? OperationStatus.Canceled : OperationStatus.Faulted;
                            if (!IsBeingWatched(mockOperationObj))
                            {
                                Notifier.Notify("Операция #" + mockOperationObj.OperationId, "Операция не завершена", null);
                            }
                        }

                        tokenSource.Cancel();

                        operation.OnChainEnded();
                        operation.Dispose();
                    }
                });

                thisOperationObj.Status = OperationStatus.Created;
                tasks.Add(task);
            }

            // Обработка и запуск выполнения цепочки
            mockOperationObj.Status = OperationStatus.Created;
            mockOperationObj.Added = DateTime.Now;
            mockOperationObj.Name = operation.OperationInfo.Name;

            AddOperation(mockOperationObj);

            AddUnit(mockOperationObj.OperationId, new OperationUnit { CancellationTokenSource = tokenSource }, operations);

            operation.OnChainStart(mockInterop);
            mockOperationObj.Status = OperationStatus.Running;

            foreach (Task task in tasks)
            {
                task.Start();
            }

            return mockOperationObj;
        }
        /// <summary>
        /// Запустить одну операцию
        /// </summary>
        /// <param name="operation">Операция</param>
        /// <exception cref="System.ArgumentNullException" />
        public OperationObject Run(IOperation operation)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            // Инициализация
            var tokenSource = new CancellationTokenSource();
            var operationObj = new OperationObject { OperationId = GetNewIndex() };
            var interop = new OperationInterop(operationObj, tokenSource.Token);

            // Chain :: Выполнение операции
            var task = new Task(() =>
            {
                operationObj.Status = OperationStatus.Running;
                operation.Execute(interop);
            },
            tokenSource.Token);

            // Chain :: Обработка законченной операции
            var chainEnd = task.ContinueWith(et =>
            {
                operationObj.Exception = et.Exception;
                operationObj.Status = et.Status.ToOperationStatus();
                operationObj.Progress = 100;
                operation.Dispose();

                if (!IsBeingWatched(operationObj))
                {
                    Notifier.Notify("Операция #" + operationObj.OperationId, "Операция завершена", null);
                }
            });

            // Обработка и запуск цепочки выполнения
            AddOperation(operationObj);
            AddUnit(operationObj.OperationId, new OperationUnit { CancellationTokenSource = tokenSource, ChainEndTask = chainEnd }, operation);

            operationObj.Status = OperationStatus.Created;
            operationObj.Name = operation.OperationInfo.Name;
            task.Start();

            return operationObj;
        }
        protected override void ExecuteExchange(OperationInterop interop)
        {
            // >>>
            interop.SetStatusText("Инициализация");
            interop.ThrowIfCancellationRequested();
            // <<<

            RaiseBeforeExecuteEvent();

            // >>>
            interop.SetStatusText("Обработка параметров");
            // <<<

            // >>>
            interop.SetStatusText("Чтение файлов");
            interop.ThrowIfCancellationRequested();
            interop.SetProgress(10);
            // <<<

            // Чтение файлов
            foreach (var formatter in Formatters)
            {
                formatter.ReadFiles(interop);
            }

            // >>>
            interop.SetStatusText("Обработка данных");
            interop.ThrowIfCancellationRequested();
            interop.SetProgress(50);
            // <<<

            // Before
            foreach (var formatter in Formatters)
            {
                formatter.OnBeforeFormatting();
            }

            // Processing
            foreach (var formatter in Formatters)
            {
                interop.ThrowIfCancellationRequested();
                var objectSpace = GetObjectSpace();
                bool success = false;
                try
                {
                    formatter.ProcessData(objectSpace, interop);
                    success = true;
                }
                finally
                {
                    CloseObjectSpace(objectSpace, success);
                }
            }

            // After
            foreach (var formatter in Formatters)
            {
                formatter.OnAfterFormatting();
            }

            // >>>
            interop.SetStatusText("Постобработка");
            interop.SetProgress(99);
            // <<<

            RaiseAfterExecuteEvent();
            interop.SetProgress(100);
        }
        protected override void CustomFormat(IEnumerable<object[]> objects, OperationInterop interop)
        {
            using (var sr = new StreamWriter(Streams.Values.Single(), Encoding ?? Encoding.Default))
            {
                var ch = new CustomHeaderEventArgs(interop);
                RaiseCustomHeaderEvent(ch);

                if (!String.IsNullOrEmpty(ch.HeaderText))
                {
                    if (listDivider == null)
                    {
                        sr.WriteLine(ch.HeaderText);
                    }
                    else
                    {
                        sr.Write(ch.HeaderText + listDivider);
                    }
                }

                foreach (var obj in objects)
                {
                    if (listDivider == null)
                    {
                        sr.WriteLine(String.Join(elemDivider, obj));
                    }
                    else
                    {
                        sr.Write(String.Join(elemDivider, obj) + listDivider);
                    }

                    interop.ThrowIfCancellationRequested();
                }

                var cf = new CustomFooterEventArgs(interop, objects);
                RaiseCustomFooterEvent(cf);

                if (!String.IsNullOrEmpty(cf.FooterText))
                {
                    if (listDivider == null)
                    {
                        sr.WriteLine(cf.FooterText);
                    }
                    else
                    {
                        sr.Write(cf.FooterText + listDivider);
                    }
                }

                sr.Flush();
            }
        }
 protected abstract void CustomFormat(IEnumerable<object[]> data, OperationInterop interop);
 public abstract void ProcessData(IObjectSpace objectSpace, OperationInterop interop);
 /// <summary>
 /// Выполнить операцию
 /// </summary>
 /// <param name="interop">Объект взаимодействия</param>
 public void Execute(OperationInterop interop)
 {
     action.Invoke(interop);
 }
 public InteropEventArgs(OperationInterop interop)
 {
     Interop = interop;
 }
 public CustomHeaderEventArgs(OperationInterop interop)
     : base(interop)
 {
 }
 public CustomFooterEventArgs(OperationInterop interop, IEnumerable<object> data)
     : base(interop)
 {
     Data = data;
 }
 protected override void ReadFile(string file, Stream stream, OperationInterop interop)
 {
     if (Reader != null) throw new InvalidOperationException("Текстовый форматировщик поддерживает только один файл.");
     Reader = new StreamReader(stream, Encoding ?? Encoding.Default);
 }
 protected override void ReadFile(string file, Stream stream, OperationInterop interop)
 {
     Workbook.LoadDocument(file, DocumentFormat);
 }