[Serializable]
public abstract class AbstractModel : ObservableObject
{
    // nothing.
}
public class RealModel : AbstractModel 
{
    public string PropertyA {get; set;}
    public string PropertyB {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这ObservableObject是来自Mvvm-light.
对于上面的模型,我使用CsvHelper如下.
AbstractModel instance = new RealModel()
                             {
                                 PropertyA = "foo",
                                 PropertyA = "bar"
                             };
using (TextWriter file = new StreamWriter("path"))
using (var csv = new CsvWriter(file))
{
    csv.WriteRecord(instance);
}
Run Code Online (Sandbox Code Playgroud)
它抛出错误如下;
没有为"AbstractModel"类型映射属性
当我设置时,它工作正常RealModel instance = new RealModel();.但是,我有各种派生类,并希望将它们保存在一个Save方法中.
我能怎么做?
不幸的是,我想说,事情本来就应该如此。输出不是 XML 文件,而是 CSV 文件。并且 CSV 文件只有一个标头(如果有的话;并非所有 CSV 文件都有标头)。
解析器无法通过行中的数据确定类。
标准 CSV 数据示例 1(名称):
ID,GivenName,FamilyName
1,John,A
2,Mike,B
Run Code Online (Sandbox Code Playgroud)
标准 CSV 数据示例 2(“周年纪念日”):
Date,Anniversary
1.1.,New year
Run Code Online (Sandbox Code Playgroud)
当您保存到 CSV 文件时,不能有两个“标题行”;解析器应该如何知道哪个子类将输出解码?名字还是纪念日?为什么第一行是“名字”,第二行是“周年纪念”?为什么不换个方式呢?
这种做法并不好。至少对于 CSV 文件来说不是。应该始终有一个表格,其中每行都有准确的列数。当数据计数始终准确时,您可以使用从您的类到通用类以及从通用类到特定数据类(用于解析器)的转换器。
非标准数据示例:(姓名和周年纪念日;无标题行):
1,John,A
1.1.,New year
2,Mike,B
Run Code Online (Sandbox Code Playgroud)
试着问问自己,解析器应该如何处理这个文件?是的,数据以“CSV 方式”存储,但我不认为这些数据是正确的。这不应该是这样的。
我知道在某些情况下,您需要使用这种方法(格式化数据;第一项指定类型,行中的所有其他值都是给定类型的数据)。但对于这种用法,您需要采用不同的方法来存储和解析数据。
不同方法的示例:
public abstract class AbstractModel : ObservableObject
{
    // no property
    protected string Prefix(object data)
    {
       if (ReferenceEquals(data, null))
         return string.Empty;
       string result = data.ToString();
       if (data.Contains(",") || data.Contains("\""))
         return $"\"{data}\"";
       return data;
    }
}
public class RealModel : AbstractModel 
{
    public string PropertyA {get; set;}
    public string PropertyB {get; set;}
    public override string ToString()
    {
       return $"{Prefix(PropertyA)},{Prefix(PropertyB)}";
    }
}
Run Code Online (Sandbox Code Playgroud)
并保存:
using (StreamWriter file = new StreamWriter("path"))
{
  foreach (AbstractModel instance in allInstances)
    file.WriteLine(instance);
}
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           502 次  |  
        
|   最近记录:  |