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 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();
            }
        }