protected BeforeFluentWriteEventArgs OnBeforeWriteRecord(ExpandoObject record, int lineNumber)
        {
            var args = new BeforeFluentWriteEventArgs(record, lineNumber);

            BeforeWriteRecord?.Invoke(this, args);

            return(args);
        }
        public override async Task WriteStreamAsync(TextWriter writer, IEnumerable <ExpandoObject> records, bool flush = true)
        {
            writer.NewLine = Environment.NewLine;
            var lineNumber = 1;

            foreach (ExpandoObject expandoObject in records)
            {
                BeforeFluentWriteEventArgs beforeWriteArgs = OnBeforeWriteRecord(expandoObject, lineNumber);

                var record = (beforeWriteArgs.LineChanged ? beforeWriteArgs.Record : expandoObject) as IDictionary <string, object>;

                if (record == null || beforeWriteArgs.SkipRecord)
                {
                    lineNumber++;
                    continue;
                }
                if (!record.ContainsKey(recordTypeProperty))
                {
                    throw new BadFluentConfigurationException($"The record must contais a property called '{recordTypeProperty}'");
                }

                MultiRecordItem recordItem = GetLineDescriptor((string)record[recordTypeProperty]);
                var             sb         = new StringBuilder();

                foreach (KeyValuePair <string, object> keyValuePair in record)
                {
                    if (!recordItem.Descriptor.Fields.TryGetValue(keyValuePair.Key, out IFieldInfoTypeDescriptor fieldDescriptor))
                    {
                        throw new Exception($"The field {keyValuePair.Key} is not configured");
                    }

                    if (fieldDescriptor.IsArray)
                    {
                        sb.Append(((IArrayFieldInfoDescriptor)fieldDescriptor).ArrayToString(
                                      (IEnumerable <dynamic>)keyValuePair.Value));
                        continue;
                    }

                    sb.Append(((IFixedFieldInfoDescriptor)fieldDescriptor).RecordToString(keyValuePair.Value));
                }
                AfterFluentWriteEventArgs afterWriteArgs = OnAfterWriteRecord(expandoObject, lineNumber, sb.ToString());

                await writer.WriteLineAsync(afterWriteArgs.Line);

                if (flush)
                {
                    await writer.FlushAsync();
                }
                lineNumber++;
            }
        }
        public override async Task WriteStreamAsync(TextWriter writer, IEnumerable <ExpandoObject> records, bool flush = true)
        {
            writer.NewLine = Environment.NewLine;
            var    lineNumber = 1;
            string delimiter  = ((DelimitedRecordDescriptor)Descriptor).Delimiter;

            foreach (ExpandoObject expandoObject in records)
            {
                BeforeFluentWriteEventArgs beforeWriteArgs = OnBeforeWriteRecord(expandoObject, lineNumber);
                var record = (beforeWriteArgs.LineChanged ? beforeWriteArgs.Record : expandoObject) as IDictionary <string, object>;

                if (record == null || beforeWriteArgs.SkipRecord)
                {
                    lineNumber++;
                    continue;
                }

                var sb = new StringBuilder();
                foreach (KeyValuePair <string, object> keyValuePair in record)
                {
                    if (!Descriptor.Fields.TryGetValue(keyValuePair.Key, out IFieldInfoTypeDescriptor fieldDescriptor))
                    {
                        throw new Exception($"The field {keyValuePair.Key} is not configured");
                    }

                    if (fieldDescriptor.IsArray)
                    {
                        sb.Append(((IDelimitedArrayFieldInfoDescriptor)fieldDescriptor).ArrayToString((IEnumerable <dynamic>)keyValuePair.Value));
                        sb.Append(delimiter);
                        continue;
                    }
                    sb.Append(
                        ((IFieldInfoDescriptor)fieldDescriptor).RecordToString(keyValuePair.Value)
                        );
                    sb.Append(delimiter);
                }
                sb.Length = sb.Length - 1;
                AfterFluentWriteEventArgs afterWriteArgs = OnAfterWriteRecord(expandoObject, lineNumber, sb.ToString());

                await writer.WriteLineAsync(afterWriteArgs.Line);

                if (flush)
                {
                    await writer.FlushAsync();
                }
                lineNumber++;
            }
        }