CsvHelper 未设置具有类路径的属性
CsvHelper not setting properties that have classpaths
我遇到一个奇怪的问题,即 CsvHelper 不会更改使用类路径保存数据的属性,例如 set => Channel.Snippet.Title
或 set => Channel.Id
。
using (StreamReader fileStream = new StreamReader(openFileDialog.FileName))
using (CsvReader reader = new CsvReader(fileStream, new CsvConfiguration(CultureInfo.InvariantCulture)
{
DetectColumnCountChanges = false,
HeaderValidated = (args) => // This is set because the CSV is only partial data
{
Console.WriteLine(args.ToString());
},
MissingFieldFound = null // This is set because the CSV is only partial data
}))
{
foreach (FullChannel record in reader.GetRecords<FullChannel>()) // tried adding .ToList()
{
Settings.Default.Channels.Add(record); // record.Id and record.Title are both null
Console.WriteLine($"Id: {record.Id} Title: {record.Title}"); // Logs: Id: Title:
record.Id = "foo"; // This works fine
record.Title = "bar"; // This works fine too
Console.WriteLine($"Id: {record.Id} Title: {record.Title}"); // Logs: Id: foo Title: bar
}
}
这总是反序列化正确的数量。我尝试创建一个新的 TestChannel
,清理并重建。如果没有类路径,CsvHelper 似乎能够保存,例如在 Title
中使用 private string title
(注释掉的代码)。
using Google.Apis.YouTube.v3.Data;
public class FullChannel
{
private string title;
public FullChannel()
{
Channel.Snippet = new ChannelSnippet();
}
// Functionality
public DateTime LastUpdated { get; set; }
public bool AllNotifications { get; set; }
// Channel
/// <summary>
/// Warning: Nothing in this property gets saved
/// </summary>
[XmlIgnore]
//public Channel Channel { get; set; } = new Channel(); // this is the original code
public TestChannel Channel { get; set; } = new TestChannel(); // this doesn't work for Id or Title
// For csv
[Name("Channel Id")]
public string Id { get => Channel.Id; set => Channel.Id = value; }
[Name("Channel Url")]
[XmlIgnore] // Generated value only
public string Url { get => $"https://www.youtube.com/channel/{Channel.Id}"; set => _ = value; }
[Name("Channel Title")]
public string Title {
//get => title;
//set => title = value;
get => Channel.Snippet.Title;
set => Channel.Snippet.Title = value;
}
}
public class TestChannel
{
public ChannelSnippet Snippet { get; set; }
public string Id { get; set; }
}
我感觉 CsvHelper 重构 class 的方式没有识别 class 路径。我唯一可以建议的是直接保存到 Channel.Snippet.Title
和 Channel.Id
.
void Main()
{
using (var fileStream = new StringReader("Channel Id,Channel Url,Channel Title\n1,this.com,MyTitle"))
using (CsvReader reader = new CsvReader(fileStream, new CsvConfiguration(CultureInfo.InvariantCulture)
{
DetectColumnCountChanges = false,
HeaderValidated = (args) => // This is set because the CSV is only partial data
{
Console.WriteLine(args.ToString());
},
MissingFieldFound = null // This is set because the CSV is only partial data
}))
{
reader.Context.RegisterClassMap<FullChannelMap>();
foreach (FullChannel record in reader.GetRecords<FullChannel>()) // tried adding .ToList()
{
Console.WriteLine($"Id: {record.Id} Title: {record.Title}"); // Logs: Id: Title:
record.Id = "foo"; // This works fine
record.Title = "bar"; // This works fine too
Console.WriteLine($"Id: {record.Id} Title: {record.Title}"); // Logs: Id: foo Title: bar
}
}
}
public class FullChannelMap : ClassMap<FullChannel>
{
public FullChannelMap()
{
Map(x => x.Channel.Id).Name("Channel Id");
Map(x => x.Channel.Snippet.Title).Name("Channel Title");
Map(x => x.Url).Name("Channel Url");
}
}
我遇到一个奇怪的问题,即 CsvHelper 不会更改使用类路径保存数据的属性,例如 set => Channel.Snippet.Title
或 set => Channel.Id
。
using (StreamReader fileStream = new StreamReader(openFileDialog.FileName))
using (CsvReader reader = new CsvReader(fileStream, new CsvConfiguration(CultureInfo.InvariantCulture)
{
DetectColumnCountChanges = false,
HeaderValidated = (args) => // This is set because the CSV is only partial data
{
Console.WriteLine(args.ToString());
},
MissingFieldFound = null // This is set because the CSV is only partial data
}))
{
foreach (FullChannel record in reader.GetRecords<FullChannel>()) // tried adding .ToList()
{
Settings.Default.Channels.Add(record); // record.Id and record.Title are both null
Console.WriteLine($"Id: {record.Id} Title: {record.Title}"); // Logs: Id: Title:
record.Id = "foo"; // This works fine
record.Title = "bar"; // This works fine too
Console.WriteLine($"Id: {record.Id} Title: {record.Title}"); // Logs: Id: foo Title: bar
}
}
这总是反序列化正确的数量。我尝试创建一个新的 TestChannel
,清理并重建。如果没有类路径,CsvHelper 似乎能够保存,例如在 Title
中使用 private string title
(注释掉的代码)。
using Google.Apis.YouTube.v3.Data;
public class FullChannel
{
private string title;
public FullChannel()
{
Channel.Snippet = new ChannelSnippet();
}
// Functionality
public DateTime LastUpdated { get; set; }
public bool AllNotifications { get; set; }
// Channel
/// <summary>
/// Warning: Nothing in this property gets saved
/// </summary>
[XmlIgnore]
//public Channel Channel { get; set; } = new Channel(); // this is the original code
public TestChannel Channel { get; set; } = new TestChannel(); // this doesn't work for Id or Title
// For csv
[Name("Channel Id")]
public string Id { get => Channel.Id; set => Channel.Id = value; }
[Name("Channel Url")]
[XmlIgnore] // Generated value only
public string Url { get => $"https://www.youtube.com/channel/{Channel.Id}"; set => _ = value; }
[Name("Channel Title")]
public string Title {
//get => title;
//set => title = value;
get => Channel.Snippet.Title;
set => Channel.Snippet.Title = value;
}
}
public class TestChannel
{
public ChannelSnippet Snippet { get; set; }
public string Id { get; set; }
}
我感觉 CsvHelper 重构 class 的方式没有识别 class 路径。我唯一可以建议的是直接保存到 Channel.Snippet.Title
和 Channel.Id
.
void Main()
{
using (var fileStream = new StringReader("Channel Id,Channel Url,Channel Title\n1,this.com,MyTitle"))
using (CsvReader reader = new CsvReader(fileStream, new CsvConfiguration(CultureInfo.InvariantCulture)
{
DetectColumnCountChanges = false,
HeaderValidated = (args) => // This is set because the CSV is only partial data
{
Console.WriteLine(args.ToString());
},
MissingFieldFound = null // This is set because the CSV is only partial data
}))
{
reader.Context.RegisterClassMap<FullChannelMap>();
foreach (FullChannel record in reader.GetRecords<FullChannel>()) // tried adding .ToList()
{
Console.WriteLine($"Id: {record.Id} Title: {record.Title}"); // Logs: Id: Title:
record.Id = "foo"; // This works fine
record.Title = "bar"; // This works fine too
Console.WriteLine($"Id: {record.Id} Title: {record.Title}"); // Logs: Id: foo Title: bar
}
}
}
public class FullChannelMap : ClassMap<FullChannel>
{
public FullChannelMap()
{
Map(x => x.Channel.Id).Name("Channel Id");
Map(x => x.Channel.Snippet.Title).Name("Channel Title");
Map(x => x.Url).Name("Channel Url");
}
}