Skip to main content
Added some best practices (static in generic type factored out, conditional access operator).
Source Link
Jesse C. Slicer
  • 14.6k
  • 1
  • 40
  • 54
namespace CsvStuff
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    publicinternal abstractstatic class CsvBase<T>CsvConstants
    {
        privatepublic static readonly char[] trimEndTrimEnd ={ new[]get; } = { ' ', ',' };

        public static char[] CsvChars { get; } = { ',', '"', ' ', '\n', '\r' };
    }

    public abstract class CsvBase<T>
    {
        private readonly IEnumerable<T> values;

        private readonly Func<T, object> getItem;

        protected CsvBase(IEnumerable<T> values, Func<T, object> getItem)
        {
            this.values = values;
            this.getItem = getItem;
        }

        public override string ToString()
        {
            var builder = new StringBuilder();

            foreach (var item in
                from element in this.values.Select(this.getItem)
                where element != null
                select element.ToString())
            {
                this.Build(builder, item).Append(", ");
            }

            return builder.ToString().TrimEnd(trimEndCsvConstants.TrimEnd);
        }

        protected abstract StringBuilder Build(StringBuilder builder, string item);
    }

    public class CsvBare<T> : CsvBase<T>
    {
        public CsvBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return builder.Append(item);
        }
    }

    public sealed class CsvTrimBare<T> : CsvBare<T>
    {
        public CsvTrimBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public class CsvRfc4180<T> : CsvBase<T>
    {
        private static readonly char[] csvChars = new[] { ',', '"', ' ', '\n', '\r' };

        public CsvRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            item = item.Replace("\"", "\"\"");
            return item.IndexOfAny(csvCharsCsvConstants.CsvChars) >= 0
                ? builder.Append("\"").Append(item).Append("\"")
                : builder.Append(item);
        }
    }

    public sealed class CsvTrimRfc4180<T> : CsvRfc4180<T>
    {
        public CsvTrimRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public class CsvAlwaysQuote<T> : CsvBare<T>
    {
        public CsvAlwaysQuote(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return builder.Append("\"").Append(item.Replace("\"", "\"\"")).Append("\"");
        }
    }

    public sealed class CsvTrimAlwaysQuote<T> : CsvAlwaysQuote<T>
    {
        public CsvTrimAlwaysQuote(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public static class CsvExtensions
    {
        public static string ToCsv<T>(this IEnumerable<T> source, Func<T, object> getItem, Type csvProcessorType)
        {
            if ((source == null)
                || (getItem == null)
                || (csvProcessorType == null)
                || !csvProcessorType.IsSubclassOf(typeof(CsvBase<T>)))
            {
                return string.Empty;
            }

            return csvProcessorType
                .GetConstructor(new[] { source.GetType(), getItem.GetType() })
                ?.Invoke(new object[] { source, getItem })
                .ToString();
        }

        private static void Main()
        {
            var words = new[] { ",this", "   is   ", "a", "test", "Super, \"luxurious\" truck" };

            Console.WriteLine(words.ToCsv(xword => xword, typeof(CsvAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(xword => xword, typeof(CsvRfc4180<string>)));
            Console.WriteLine(words.ToCsv(xword => xword, typeof(CsvBare<string>)));
            Console.WriteLine(words.ToCsv(xword => xword, typeof(CsvTrimAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(xword => xword, typeof(CsvTrimRfc4180<string>)));
            Console.WriteLine(words.ToCsv(xword => xword, typeof(CsvTrimBare<string>)));
            Console.ReadLine();
        }
    }
}
namespace CsvStuff
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public abstract class CsvBase<T>
    {
        private static readonly char[] trimEnd = new[] { ' ', ',' };

        private readonly IEnumerable<T> values;

        private readonly Func<T, object> getItem;

        protected CsvBase(IEnumerable<T> values, Func<T, object> getItem)
        {
            this.values = values;
            this.getItem = getItem;
        }

        public override string ToString()
        {
            var builder = new StringBuilder();

            foreach (var item in
                from element in this.values.Select(this.getItem)
                where element != null
                select element.ToString())
            {
                this.Build(builder, item).Append(", ");
            }

            return builder.ToString().TrimEnd(trimEnd);
        }

        protected abstract StringBuilder Build(StringBuilder builder, string item);
    }

    public class CsvBare<T> : CsvBase<T>
    {
        public CsvBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return builder.Append(item);
        }
    }

    public sealed class CsvTrimBare<T> : CsvBare<T>
    {
        public CsvTrimBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public class CsvRfc4180<T> : CsvBase<T>
    {
        private static readonly char[] csvChars = new[] { ',', '"', ' ', '\n', '\r' };

        public CsvRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            item = item.Replace("\"", "\"\"");
            return item.IndexOfAny(csvChars) >= 0
                ? builder.Append("\"").Append(item).Append("\"")
                : builder.Append(item);
        }
    }

    public sealed class CsvTrimRfc4180<T> : CsvRfc4180<T>
    {
        public CsvTrimRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public class CsvAlwaysQuote<T> : CsvBare<T>
    {
        public CsvAlwaysQuote(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return builder.Append("\"").Append(item.Replace("\"", "\"\"")).Append("\"");
        }
    }

    public sealed class CsvTrimAlwaysQuote<T> : CsvAlwaysQuote<T>
    {
        public CsvTrimAlwaysQuote(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public static class CsvExtensions
    {
        public static string ToCsv<T>(this IEnumerable<T> source, Func<T, object> getItem, Type csvProcessorType)
        {
            if ((source == null)
                || (getItem == null)
                || (csvProcessorType == null)
                || !csvProcessorType.IsSubclassOf(typeof(CsvBase<T>)))
            {
                return string.Empty;
            }

            return csvProcessorType
                .GetConstructor(new[] { source.GetType(), getItem.GetType() })
                .Invoke(new object[] { source, getItem })
                .ToString();
        }

        private static void Main()
        {
            var words = new[] { ",this", "   is   ", "a", "test", "Super, \"luxurious\" truck" };

            Console.WriteLine(words.ToCsv(x => x, typeof(CsvAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvRfc4180<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvBare<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimRfc4180<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimBare<string>)));
            Console.ReadLine();
        }
    }
}
namespace CsvStuff
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    internal static class CsvConstants
    {
        public static char[] TrimEnd { get; } = { ' ', ',' };

        public static char[] CsvChars { get; } = { ',', '"', ' ', '\n', '\r' };
    }

    public abstract class CsvBase<T>
    {
        private readonly IEnumerable<T> values;

        private readonly Func<T, object> getItem;

        protected CsvBase(IEnumerable<T> values, Func<T, object> getItem)
        {
            this.values = values;
            this.getItem = getItem;
        }

        public override string ToString()
        {
            var builder = new StringBuilder();

            foreach (var item in
                from element in this.values.Select(this.getItem)
                where element != null
                select element.ToString())
            {
                this.Build(builder, item).Append(", ");
            }

            return builder.ToString().TrimEnd(CsvConstants.TrimEnd);
        }

        protected abstract StringBuilder Build(StringBuilder builder, string item);
    }

    public class CsvBare<T> : CsvBase<T>
    {
        public CsvBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return builder.Append(item);
        }
    }

    public sealed class CsvTrimBare<T> : CsvBare<T>
    {
        public CsvTrimBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public class CsvRfc4180<T> : CsvBase<T>
    {
        public CsvRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            item = item.Replace("\"", "\"\"");
            return item.IndexOfAny(CsvConstants.CsvChars) >= 0
                ? builder.Append("\"").Append(item).Append("\"")
                : builder.Append(item);
        }
    }

    public sealed class CsvTrimRfc4180<T> : CsvRfc4180<T>
    {
        public CsvTrimRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public class CsvAlwaysQuote<T> : CsvBare<T>
    {
        public CsvAlwaysQuote(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return builder.Append("\"").Append(item.Replace("\"", "\"\"")).Append("\"");
        }
    }

    public sealed class CsvTrimAlwaysQuote<T> : CsvAlwaysQuote<T>
    {
        public CsvTrimAlwaysQuote(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public static class CsvExtensions
    {
        public static string ToCsv<T>(this IEnumerable<T> source, Func<T, object> getItem, Type csvProcessorType)
        {
            if ((source == null)
                || (getItem == null)
                || (csvProcessorType == null)
                || !csvProcessorType.IsSubclassOf(typeof(CsvBase<T>)))
            {
                return string.Empty;
            }

            return csvProcessorType
                .GetConstructor(new[] { source.GetType(), getItem.GetType() })
                ?.Invoke(new object[] { source, getItem })
                .ToString();
        }

        private static void Main()
        {
            var words = new[] { ",this", "   is   ", "a", "test", "Super, \"luxurious\" truck" };

            Console.WriteLine(words.ToCsv(word => word, typeof(CsvAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(word => word, typeof(CsvRfc4180<string>)));
            Console.WriteLine(words.ToCsv(word => word, typeof(CsvBare<string>)));
            Console.WriteLine(words.ToCsv(word => word, typeof(CsvTrimAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(word => word, typeof(CsvTrimRfc4180<string>)));
            Console.WriteLine(words.ToCsv(word => word, typeof(CsvTrimBare<string>)));
            Console.ReadLine();
        }
    }
}
took into account @w0lf's quoting comment and used inheritance better.
Source Link
Jesse C. Slicer
  • 14.6k
  • 1
  • 40
  • 54
namespace CsvStuff
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public abstract class CsvBase<T>
    {
        private static readonly char[] trimEnd = new[] { ' ', ',' };

        private readonly IEnumerable<T> values;

        private readonly Func<T, object> getItem;

        protected CsvBase(IEnumerable<T> values, Func<T, object> getItem)
        {
            this.values = values;
            this.getItem = getItem;
        }

        public override string ToString()
        {
            var builder = new StringBuilder();

            foreach (var stritem in
                from itemelement in this.values.Select(this.getItem)
                where itemelement != null
                select itemelement.ToString())
            {
                this.Build(builder, stritem).Append(", ");
            }

            return builder.ToString().TrimEnd(trimEnd);
        }

        protected abstract StringBuilder Build(StringBuilder builder, string stritem);
    }

    public sealed class CsvBare<T> : CsvBase<T>
    {
        public CsvBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string stritem)
        {
            return builder.Append(str).Append(", "item);
        }
    }

    public sealed class CsvTrimBare<T> : CsvBase<T>CsvBare<T>
    {
        public CsvTrimBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string stritem)
        {
            return builderbase.AppendBuild(strbuilder, item.Trim()).Append(", ");
        }
    }

    public sealed class CsvRfc4180<T> : CsvBase<T>
    {
        private static readonly char[] csvChars = new[] { ',', '"', ' ', '\n', '\r' };

        public CsvRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string stritem)
        {
            item = item.Replace("\"", "\"\"");
            return stritem.IndexOfAny(csvChars) >= 0
                ? builder.Append("\"").Append(stritem).Append("\"").Append(", ")
                : builder.Append(str).Append(", "item);
        }
    }

    public sealed class CsvTrimRfc4180<T> : CsvBase<T>CsvRfc4180<T>
    {
        private static readonly char[] csvChars = new[] { ',', '"', ' ', '\n', '\r' };

        public CsvTrimRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string stritem)
        {
            return strbase.IndexOfAnyBuild(csvCharsbuilder, item.Trim());
 >= 0      }
    }

    public class CsvAlwaysQuote<T> : CsvBare<T>
    ?{
 builder.Append("\"").Append(str.Trim       public CsvAlwaysQuote()IEnumerable<T> values, Func<T, object> getItem).Append : base("\""values, getItem).Append
        {
        }

        protected override StringBuilder Build("StringBuilder builder, "string item)
        {
        :    return builder.Append(str"\"").TrimAppend(item.Replace("\"", "\"\"")).Append(", ""\"");
        }
    }

    public sealed class CsvTrimAlwaysQuote<T> : CsvAlwaysQuote<T>
    {
        public CsvTrimAlwaysQuote(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public static class CsvExtensions
    {
        public static string ToCsv<T>(this IEnumerable<T> source, Func<T, object> getItem, Type csvProcessorType)
        {
            if ((source == null)
                || (getItem == null)
                || (csvProcessorType == null)
                || !csvProcessorType.IsSubclassOf(typeof(CsvBase<T>)))
            {
                return string.Empty;
            }

            return csvProcessorType
                .GetConstructor(new[] { source.GetType(), getItem.GetType() })
                .Invoke(new object[] { source, getItem })
                .ToString();
        }

        private static void Main()
        {
            var words = new[] { ",this", "   is   ", "a", "test", "Super, \"luxurious\" truck" };

            Console.WriteLine(words.ToCsv(x => x, typeof(CsvAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvRfc4180<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvBare<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimRfc4180<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimBare<string>)));
            Console.ReadLine();
        }

     }
}
namespace CsvStuff
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public abstract class CsvBase<T>
    {
        private static readonly char[] trimEnd = new[] { ' ', ',' };

        private readonly IEnumerable<T> values;

        private readonly Func<T, object> getItem;

        protected CsvBase(IEnumerable<T> values, Func<T, object> getItem)
        {
            this.values = values;
            this.getItem = getItem;
        }

        public override string ToString()
        {
            var builder = new StringBuilder();

            foreach (var str in from item in this.values.Select(this.getItem) where item != null select item.ToString())
            {
                this.Build(builder, str);
            }

            return builder.ToString().TrimEnd(trimEnd);
        }

        protected abstract StringBuilder Build(StringBuilder builder, string str);
    }

    public sealed class CsvBare<T> : CsvBase<T>
    {
        public CsvBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string str)
        {
            return builder.Append(str).Append(", ");
        }
    }

    public sealed class CsvTrimBare<T> : CsvBase<T>
    {
        public CsvTrimBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string str)
        {
            return builder.Append(str.Trim()).Append(", ");
        }
    }

    public sealed class CsvRfc4180<T> : CsvBase<T>
    {
        private static readonly char[] csvChars = new[] { ',', '"', ' ', '\n', '\r' };

        public CsvRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string str)
        {
            return str.IndexOfAny(csvChars) >= 0
                ? builder.Append("\"").Append(str).Append("\"").Append(", ")
                : builder.Append(str).Append(", ");
        }
    }

    public sealed class CsvTrimRfc4180<T> : CsvBase<T>
    {
        private static readonly char[] csvChars = new[] { ',', '"', ' ', '\n', '\r' };

        public CsvTrimRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string str)
        {
            return str.IndexOfAny(csvChars) >= 0
                ? builder.Append("\"").Append(str.Trim()).Append("\"").Append(", ")
                : builder.Append(str.Trim()).Append(", ");
        }
    }

    public static class CsvExtensions
    {
        public static string ToCsv<T>(this IEnumerable<T> source, Func<T, object> getItem, Type csvProcessorType)
        {
            if ((source == null)
                || (getItem == null)
                || (csvProcessorType == null)
                || !csvProcessorType.IsSubclassOf(typeof(CsvBase<T>)))
            {
                return string.Empty;
            }

            return csvProcessorType
                .GetConstructor(new[] { source.GetType(), getItem.GetType() })
                .Invoke(new object[] { source, getItem })
                .ToString();
        }

        private static void Main()
        {
            var words = new[] { ",this", "   is   ", "a", "test" };

            Console.WriteLine(words.ToCsv(x => x, typeof(CsvRfc4180<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvBare<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimRfc4180<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimBare<string>)));
            Console.ReadLine();
        }

     }
}
namespace CsvStuff
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public abstract class CsvBase<T>
    {
        private static readonly char[] trimEnd = new[] { ' ', ',' };

        private readonly IEnumerable<T> values;

        private readonly Func<T, object> getItem;

        protected CsvBase(IEnumerable<T> values, Func<T, object> getItem)
        {
            this.values = values;
            this.getItem = getItem;
        }

        public override string ToString()
        {
            var builder = new StringBuilder();

            foreach (var item in
                from element in this.values.Select(this.getItem)
                where element != null
                select element.ToString())
            {
                this.Build(builder, item).Append(", ");
            }

            return builder.ToString().TrimEnd(trimEnd);
        }

        protected abstract StringBuilder Build(StringBuilder builder, string item);
    }

    public class CsvBare<T> : CsvBase<T>
    {
        public CsvBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return builder.Append(item);
        }
    }

    public sealed class CsvTrimBare<T> : CsvBare<T>
    {
        public CsvTrimBare(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public class CsvRfc4180<T> : CsvBase<T>
    {
        private static readonly char[] csvChars = new[] { ',', '"', ' ', '\n', '\r' };

        public CsvRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            item = item.Replace("\"", "\"\"");
            return item.IndexOfAny(csvChars) >= 0
                ? builder.Append("\"").Append(item).Append("\"")
                : builder.Append(item);
        }
    }

    public sealed class CsvTrimRfc4180<T> : CsvRfc4180<T>
    {
        public CsvTrimRfc4180(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public class CsvAlwaysQuote<T> : CsvBare<T>
    {
        public CsvAlwaysQuote(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return builder.Append("\"").Append(item.Replace("\"", "\"\"")).Append("\"");
        }
    }

    public sealed class CsvTrimAlwaysQuote<T> : CsvAlwaysQuote<T>
    {
        public CsvTrimAlwaysQuote(IEnumerable<T> values, Func<T, object> getItem) : base(values, getItem)
        {
        }

        protected override StringBuilder Build(StringBuilder builder, string item)
        {
            return base.Build(builder, item.Trim());
        }
    }

    public static class CsvExtensions
    {
        public static string ToCsv<T>(this IEnumerable<T> source, Func<T, object> getItem, Type csvProcessorType)
        {
            if ((source == null)
                || (getItem == null)
                || (csvProcessorType == null)
                || !csvProcessorType.IsSubclassOf(typeof(CsvBase<T>)))
            {
                return string.Empty;
            }

            return csvProcessorType
                .GetConstructor(new[] { source.GetType(), getItem.GetType() })
                .Invoke(new object[] { source, getItem })
                .ToString();
        }

        private static void Main()
        {
            var words = new[] { ",this", "   is   ", "a", "test", "Super, \"luxurious\" truck" };

            Console.WriteLine(words.ToCsv(x => x, typeof(CsvAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvRfc4180<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvBare<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimAlwaysQuote<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimRfc4180<string>)));
            Console.WriteLine(words.ToCsv(x => x, typeof(CsvTrimBare<string>)));
            Console.ReadLine();
        }
    }
}
Added a check to make sure the CSV processor was a subclass of the correct base class.
Source Link
Jesse C. Slicer
  • 14.6k
  • 1
  • 40
  • 54
Loading
a bit more OOish.
Source Link
Jesse C. Slicer
  • 14.6k
  • 1
  • 40
  • 54
Loading
fixed > to >=.
Source Link
Jesse C. Slicer
  • 14.6k
  • 1
  • 40
  • 54
Loading
Source Link
Jesse C. Slicer
  • 14.6k
  • 1
  • 40
  • 54
Loading