サーバーからフェッチされるさまざまなフィールドを持つワーカーがあります。このクラスをExcelシートに変換するためにCSVHelperパッケージを使用しています。ワーカーには次のようなフィールドがあります。
class Worker
{
string name;
string phone;
string age;
Dictionary<string,object> customerField;
}
私は名前、電話、番号をマップできます
class WorkerMap : CsvClassMap<Worker>
{
public WorkerMap()
{
Map(m => m.name);
Map(m => m.phone);
Map(m => m.age);
}
}
そして、私はマップを生成します:
csv.Configuration.RegisterClassMap<WorkerMap>();
によって労働者のリストを書いてください:
csv.WriteRecords(workerList);
CustomerFieldディクショナリをExcelシートにマップして、キー(文字列)が別の列名になり、値(オブジェクト)が列の値になるようにするにはどうすればよいですか。
CSVHelperは実行時にそれを行うのに役立ちますか?ドキュメントを確認しました。私のために働く何かを見つけることができませんでした。
現時点では、辞書の作成はサポートされていないと思います。 1つには、CsvHelperはどのヘッダーを書き込むかを知るのが難しいでしょう。幸い、CsvWriterを手動で使用して一度にフィールドを書き込むのはそれほど複雑ではありません。各ワーカーのcustomerField
に同じキーがあると仮定すると、コードは次のようになります。
var firstWorker = workerList.First();
var keys = firstWorker.customerField.Keys.ToList();
var headers = new []{ "name", "phone", "age"}.Concat(keys).ToList();
var csv = new CsvWriter( textWriter );
// Write the headers
foreach( var header in headers )
{
csv.WriteField(header);
}
csv.NextRecord();
// Write the rows
foreach( var item in workerList)
{
csv.WriteField(item.name);
csv.WriteField(item.phone);
csv.WriteField(item.age);
var dict = worker.customerField;
foreach (var key in keys)
{
csv.WriteField(dict[key]);
}
csv.NextRecord();
}
このコードはテストされていませんが、必要な動作にかなり近いはずです。 customerField
辞書キーがリストで一貫していない場合、コードは少し複雑になりますが、解決可能です。
辞書はサポートされていませんが、ExpandoObjectはサポートされています。
上記の最初のリンクをたどると、50行目と57行目でWriteDynamicHeaderメソッドが使用されています。
拡張メソッドを使用して、各レコードのExpandoObjectを作成し、CsvHelperを使用してそのオブジェクトを書き込みます。document
という名前のDictionary<string, object>
パラメーターは、CSVレコードの作成元です。
public static class DictionaryCsvExtentions
{
public static dynamic BuildCsvObject(this Dictionary<string, object> document)
{
dynamic csvObj = new ExpandoObject();
foreach (var p in document)
{
AddProperty(csvObj, p.Key, p.Value);
}
return csvObj;
}
private static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
{
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
{
expandoDict[propertyName] = propertyValue;
}
else
{
expandoDict.Add(propertyName, propertyValue);
}
}
}
これで、このような辞書からExpandoObjectを作成できます
var csvObj = myDictonary.BuildCsvObject();
これで、上記のリンクにあるJoshのテストに従って、CsvHelperとかなりシームレスに辞書を使用するために必要なすべてが揃いました。私はこれがマイケルのより良い解決策ではないと思います、ただ違うアプローチです。
クレジットは、クレジットが原因のディクショナリコードからの基本的なExpandoObjectがここにあります(詳細な説明があります!) https://www.oreilly.com/learning/building-c-objects-dynamically