using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using CsvHelper.Configuration;
using CsvHelper.Configuration.Attributes;
using CsvHelper.Expressions;
using CsvHelper.TypeConversion;
public string OrderNumber { get; set; }
public string RecipientName { get; set; }
public sealed class OrderMap : ClassMap<Order>
Map(o => o.OrderNumber).Name("ActivityId");
Map(o => o.RecipientName).Name("LocationName");
public static async Task Test()
var originalRecords = new List<Order>()
new () { OrderNumber = "101", RecipientName = "hello" },
new () { OrderNumber = "202", RecipientName = "there" },
var file = new MockFileInfo<Order, OrderMap>(originalRecords);
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
using (var reader = new StreamReader(file.OpenReadStream()))
using (var csv = new CsvReader(reader, config))
csv.Context.RegisterClassMap<OrderMap>();
var records = csv.GetRecordsAsync<Order>();
await foreach (var order in records)
Console.WriteLine(order.OrderNumber);
class MockFileInfo<TRecord, TClassMap> where TClassMap : ClassMap<TRecord>
public MockFileInfo(List<TRecord> records) => this.records = records;
public Stream OpenReadStream()
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
var innerStream = new MemoryStream();
using (var writer = new StreamWriter(innerStream, leaveOpen : true))
using (var csv = new CsvWriter(writer, config))
csv.Context.RegisterClassMap<TClassMap>();
csv.WriteRecords(records);
innerStream.Position = 0;
Console.WriteLine(Encoding.UTF8.GetString(innerStream.GetBuffer(), 0, checked((int)innerStream.Length)));
return new AsyncOnlySurogateStream(innerStream);
public class SurrogateStream : Stream
Stream BaseStream => baseStream ?? throw new ObjectDisposedException(nameof(BaseStream));
public SurrogateStream(Stream baseStream) => this.baseStream = baseStream ?? throw new ArgumentNullException(nameof(baseStream));
public override long Length => BaseStream.Length;
public override long Position { get => BaseStream.Position; set => BaseStream.Position = value; }
public override bool CanRead => BaseStream.CanRead;
public override bool CanWrite => BaseStream.CanWrite;
public override bool CanSeek => BaseStream.CanSeek;
public override bool CanTimeout => BaseStream.CanTimeout;
public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => BaseStream.BeginRead(buffer, offset, count, callback, state);
public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => BaseStream.BeginWrite(buffer, offset, count, callback, state);
public override void CopyTo (System.IO.Stream destination, int bufferSize) => BaseStream.CopyTo(destination, bufferSize);
public override Task CopyToAsync (System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) => BaseStream.CopyToAsync(destination, bufferSize, cancellationToken);
protected override void Dispose (bool disposing)
Interlocked.Exchange(ref baseStream, null)?.Dispose();
public override ValueTask DisposeAsync() => Interlocked.Exchange(ref baseStream, null)?.DisposeAsync() ?? ValueTask.CompletedTask;
public override int EndRead (IAsyncResult asyncResult) => BaseStream.EndRead(asyncResult);
public override void EndWrite (IAsyncResult asyncResult) => BaseStream.EndWrite(asyncResult);
public override void Flush() => BaseStream.Flush();
public override Task FlushAsync (CancellationToken cancellationToken) => BaseStream.FlushAsync(cancellationToken);
public override int Read (byte[] buffer, int offset, int count) => BaseStream.Read(buffer, offset, count);
public override int Read (Span<byte> buffer) => BaseStream.Read(buffer);
public override Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken) => BaseStream.ReadAsync(buffer, offset, count, cancellationToken);
public override ValueTask<int> ReadAsync (Memory<byte> buffer, System.Threading.CancellationToken cancellationToken = default) => BaseStream.ReadAsync(buffer, cancellationToken);
public override int ReadByte () => BaseStream.ReadByte();
public override long Seek (long offset, System.IO.SeekOrigin origin) => BaseStream.Seek(offset, origin);
public override void SetLength (long value) => BaseStream.SetLength(value);
public override void Write (byte[] buffer, int offset, int count) => BaseStream.Write(buffer, offset, count);
public override void Write (ReadOnlySpan<byte> buffer) => BaseStream.Write(buffer);
public override System.Threading.Tasks.Task WriteAsync (byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => BaseStream.WriteAsync(buffer, offset, count, cancellationToken);
public override System.Threading.Tasks.ValueTask WriteAsync (ReadOnlyMemory<byte> buffer, System.Threading.CancellationToken cancellationToken = default) => BaseStream.WriteAsync(buffer, cancellationToken);
public override void WriteByte (byte value) => BaseStream.WriteByte(value);
public class AsyncOnlySurogateStream : SurrogateStream
public AsyncOnlySurogateStream(Stream baseStream) : base(baseStream) { }
public override void CopyTo (System.IO.Stream destination, int bufferSize) => throw new InvalidOperationException(string.Format("Non async method {0} called", System.Reflection.MethodBase.GetCurrentMethod()?.Name));
protected override void Dispose (bool disposing)
throw new InvalidOperationException(string.Format("Non async method {0} called", System.Reflection.MethodBase.GetCurrentMethod()?.Name));
public override void Flush() => throw new InvalidOperationException(string.Format("Non async method {0} called", System.Reflection.MethodBase.GetCurrentMethod()?.Name));
public override int Read (byte[] buffer, int offset, int count) => throw new InvalidOperationException(string.Format("Non async method {0} called", System.Reflection.MethodBase.GetCurrentMethod()?.Name));
public override int Read (Span<byte> buffer) => throw new InvalidOperationException(string.Format("Non async method {0} called", System.Reflection.MethodBase.GetCurrentMethod()?.Name));
public override int ReadByte () => throw new InvalidOperationException(string.Format("Non async method {0} called", System.Reflection.MethodBase.GetCurrentMethod()?.Name));
public override void Write (byte[] buffer, int offset, int count) => throw new InvalidOperationException(string.Format("Non async method {0} called", System.Reflection.MethodBase.GetCurrentMethod()?.Name));
public override void Write (ReadOnlySpan<byte> buffer) => throw new InvalidOperationException(string.Format("Non async method {0} called", System.Reflection.MethodBase.GetCurrentMethod()?.Name));
public override void WriteByte (byte value) => throw new InvalidOperationException(string.Format("Non async method {0} called", System.Reflection.MethodBase.GetCurrentMethod()?.Name));
public static async Task Main(string[] args)
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version);
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Assembly.GetName().Name, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("{0} version: {1}", typeof(CsvReader).Assembly.GetName().Name, typeof(CsvReader).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");