using System;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.IO;
using System.Text;
namespace CsvWriter
{
class Program
{
static void Main(string[] args)
{
try
{
var basicList = new List<ICsvFieldsDto>();
for (int i = 0; i < 10; i++)
{
var basic = new BasicDto();
basic.Id = i.ToString();
basic.Name = "Name" + i;
basic.Memo = "Memo" + i;
basicList.Add(basic);
}
var csvWriter = new CsvWriter();
csvWriter.Write(basicList, "example.csv", false);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.Write("終了");
Console.Read();
}
}
/// <summary>
/// CSV書き込み
/// </summary>
class CsvWriter
{
internal void Write(List<ICsvFieldsDto> csvFieldsDtoList, string path, bool appends)
{
List<List<string>> csvRecords = csvFieldsDtoList.Select(csvFieldsDto => GetCsvFieldValueListByProperties(csvFieldsDto)).ToList();
using (var sw = new StreamWriter(path, appends))//, Encoding.GetEncoding("shift_jis")))
{
csvRecords.ForEach(record =>
{
sw.WriteLine(String.Join(",", record));
});
}
}
/// <summary>
/// 引数のDTOのCsvFied属性の付いたプロパティの値を、CSV出力におけるフィールド順の値のリストに変換
/// </summary>
/// <returns>CSV出力におけるフィールド順の値のリスト</returns>
/// <param name="csvFieldsDto">CSVFieldsDtoインターフェースを実装したクラス</param>
private List<string> GetCsvFieldValueListByProperties(ICsvFieldsDto csvFieldsDto)
{
// CSVFied属性の付いたプロパティを指定された順番でリストする
var csvFieldProperties = csvFieldsDto.GetType()
.GetProperties()
.Where(property => property.GetCustomAttributes(typeof(CsvFieldAttribute), true).Length > 0)
.OrderBy(property => ((CsvFieldAttribute)property.GetCustomAttributes(typeof(CsvFieldAttribute), true).First()).Order);
if (!csvFieldProperties.All(csvProperty => csvProperty.PropertyType == typeof(string)))
{
// string型のみCSV出力の対象とする
throw new InvalidOperationException("String type is only valid for CsvField.");
}
// 特定文字の置換・削除を行い、ダブルクォート付加をしたうえで、値のリストにして返却
var csvFields = csvFieldProperties.Select(property =>
{
var value = (string)property.GetValue(csvFieldsDto);
var csvFieldAttr = (CsvFieldAttribute)property.GetCustomAttributes(typeof(CsvFieldAttribute)).First();
if (csvFieldAttr.NeedsCharReplacing)
{
// 要件に定められた文字の置換
}
if (csvFieldAttr.NeedsCharRemoving)
{
// 要件に定められた文字の削除
}
return "\"" + value + "\"";
}).ToList();
return csvFields;
}
}
/// <summary>
/// CSVのフィールドをプロパティとして持つことを表すマーカーインターフェース
/// </summary>
/// <remarks>
/// CSVのフィールドとして出力したいstring型のpublicなプロパティにCsvField属性を付与してください。
/// </remarks>
interface ICsvFieldsDto { }
/// <summary>
/// CSV出力の対象フィールドであることを示すAttribute
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
class CsvFieldAttribute : Attribute
{
/// <summary>
/// 何番目のフィールドか
/// </summary>
/// <value>The order.</value>
public int Order { get; set; }
/// <summary>
/// 置換が必要な文字が存在するか
/// </summary>
/// <value><c>true</c> if needs char replacing; otherwise, <c>false</c>.</value>
public bool NeedsCharReplacing { get; set; }
/// <summary>
/// 削除が必要な文字が存在するか
/// </summary>
/// <value><c>true</c> if needs char replacing; otherwise, <c>false</c>.</value>
public bool NeedsCharRemoving { get; set; }
public CsvFieldAttribute(int order)
{
this.Order = order;
}
}
/// <summary>
/// DTO Example
/// </summary>
class BasicDto : ICsvFieldsDto
{
[CsvField(1)]
public string Id { set; get; }
[CsvField(2)]
public string Name { set; get; }
[CsvField(3, NeedsCharReplacing = true)]
public string Memo { set; get; }
}
}