using DocumentFormat.OpenXml.Drawing.Diagrams; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; namespace System.Text.Csv { #nullable enable public class CsvSerializer { private readonly PropertyInfo[] props; private readonly static Regex numbers = new Regex(@"^[0-9\-\+\.]+$"); public string Separator { get; set; } = ";"; public string NewLine { get; set; } = "\r\n"; public string Quot { get; set; } = "\""; public Encoding Encoding { get; set; } = Encoding.UTF8; public string FloatingPointFormat { get; set; } = "#0.000#"; public string DateTimeFormat { get; set; } = "yyyy-MM-dd HH:mm:ss"; public string objDateTimeOffsetFormat { get; set; } = "yyyy-MM-dd HH:mm:ss zzz"; public string TimeOnlyFormat { get; set; } = "HH:mm:ss"; public string DateOnlyFormat { get; set; } = "yyyy-MM-dd"; public CsvSerializer() { props = typeof(T).GetProperties(); } public void Serialize(IEnumerable data, Stream toStream) { if (!data.Any()) return; if(!props.Any()) return; void HandleRow(IEnumerable rowData) { var row = string.Join(Separator, rowData); var bytes = Encoding.GetBytes(row + NewLine); toStream.Write(bytes); } HandleRow(props.Select(p => p.Name)); foreach ( var item in data) HandleRow(props.Select(p => CsvSerializer.Escape(Fromat(p.GetValue(item))))); } private string Fromat(object? obj) { if (obj is double objDouble) return objDouble.ToString(FloatingPointFormat); if (obj is float objfloat) return objfloat.ToString(FloatingPointFormat); if (obj is DateTime objDateTime) return objDateTime.ToString(DateTimeFormat); if (obj is DateTimeOffset objDateTimeOffset) return objDateTimeOffset.ToString(objDateTimeOffsetFormat); if (obj is DateOnly objDateOnly) return objDateOnly.ToString(DateOnlyFormat); if (obj is TimeOnly objTimeOnly) return objTimeOnly.ToString(TimeOnlyFormat); return obj?.ToString() ?? string.Empty; } private static string Escape(string inString) { if (numbers.IsMatch(inString)) return inString; return $"\"{inString}\""; } } #nullable disable }