5
[Serializable]
public abstract class AbstractModel : ObservableObject
{
    // nothing.
}

public class RealModel : AbstractModel 
{
    public string PropertyA {get; set;}
    public string PropertyB {get; set;}
}

请注意,这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);
}

它抛出如下错误;

没有为“AbstractModel”类型映射任何属性

当我设置时它工作正常RealModel instance = new RealModel();。但是,我有各种派生类,并希望将它们保存在一个 Save 方法中。

我能怎么做?

4

2 回答 2

2

我知道这已经三岁了,但我试图做同样的事情,我找到了一个让它工作的黑客。

csvHelper 中的违规代码如下:

public virtual Type GetTypeForRecord<T>(T record)
{
    var type = typeof(T);
    if (type == typeof(object))
    {
        type = record.GetType();
    }

    return type;
}

传递给此方法的 C# 泛型是在编译时确定的,因此 T 始终是基类,而不是派生类,但如果object在调用之前强制转换为 type WriteRecord,该方法将使用GetType(),这将返回派生类型。

AbstractModel instance = new RealModel()
                             {
                                 PropertyA = "foo",
                                 PropertyA = "bar"
                             };

using (TextWriter file = new StreamWriter("path"))
using (var csv = new CsvWriter(file))
{
    csv.WriteRecord((object)instance);
}
于 2019-02-20T22:05:23.903 回答
0

不幸的是,我会说,这就是它应该的方式。输出不是 XML 文件,而是 CSV 文件。并且 CSV 文件只有一个标题(如果有;并非所有 CSV 文件都有标题)。

解析器无法通过在线数据确定类。

标准 CSV 数据示例 1(名称):

ID,GivenName,FamilyName
1,John,A
2,Mike,B

标准 CSV 数据示例 2(“周年纪念日”):

Date,Anniversary
1.1.,New year

保存为 CSV 文件时,不能有两个“标题行”;解析器应该如何知道将输出解码到哪个子类?名字还是纪念日?为什么第一行是“姓名”,第二行是“纪念日”?为什么不是另一种方式?

这种方法不好。至少不是 CSV 文件。应该总是有一个表,每行都有精确的列数。当数据计数始终准确时,您可以将您的类转换为通用类,从通用类转换为特定数据类(用于解析器)。

非标准数据示例:(姓名和纪念日;无标题行):

1,John,A
1.1.,New year
2,Mike,B

试着问问自己,解析器应该如何处理这个文件?是的,数据以“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)}";
    }
}

并保存:

using (StreamWriter file = new StreamWriter("path"))
{
  foreach (AbstractModel instance in allInstances)
    file.WriteLine(instance);
}
于 2016-01-05T10:41:57.003 回答