[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方法中。
我该怎么办?
答案 0 :(得分:0)
不幸的是我会说,这就是应该的样子。 输出不是XML文件,而是CSV文件。并且CSV文件只有一个标题(当它有任何标题时;并非所有CSV文件都有标题)。
解析器无法按行数据确定类。
标准CSV数据示例1(名称):
namespace Application
{
[Activity(Label = "WebPage", Theme = "@android:style/Theme.NoTitleBar")]
public class WebPage : Activity
{
public bool isSchedule;
private WebView _webView;
private string _url;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.WebPage);
_webView = FindViewById<WebView>(Resource.Id.webView);
new DisplayWebPage(_webView, GetUrl());
}
public string GetUrl()
{
return _url;
}
public void SetUrl(string sUrl)
{
_url = sUrl;
}
private void ButtonCLicked()
{
if (isSchedule == true)
{
SetUrl("https://www.google.com");
Toast.MakeText(this, "isSchedule is true", ToastLength.Short).Show();
}
}
}
}
标准CSV数据示例2(&#34;纪念日&#34;):
ID,GivenName,FamilyName
1,John,A
2,Mike,B
当您保存到CSV文件时,您不能有两个&#34;标题行&#34 ;;解析器应该如何知道哪个子类解码输出?姓名或纪念日?为什么第一行&#34;名称&#34;和第二个&#34;周年纪念&#34;?为什么不是另一种方式?
这种方法并不好。至少不适用于CSV文件。应始终有一个表格,每行都有精确的列数。 当数据的计数总是精确的时,您可以将类转换为通用类,从通用类转换为特定数据类(用于解析器)。
非标准数据示例:(姓名和纪念日;没有标题行):
Date,Anniversary
1.1.,New year
试着问自己,解析器应该如何处理这个文件?是的,数据存储在&#34; CSV方式&#34;,但我不认为,这些数据是正确的。这不是应该的方式。
我知道有些情况,当你需要使用这种方法时(格式化数据;第一项指定类型,行中的所有其他值都是给定类型的数据)。但是对于这种用法,您需要采用不同的方法来存储和解析数据。
不同方法的一个例子:
1,John,A
1.1.,New year
2,Mike,B
并保存:
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)}";
}
}
答案 1 :(得分:0)
我知道这已经三岁了,但是我试图做同样的事情,但是我发现了一个可以使其正常工作的黑客。
csvHelper中令人反感的代码如下:
public virtual Type GetTypeForRecord<T>(T record)
{
var type = typeof(T);
if (type == typeof(object))
{
type = record.GetType();
}
return type;
}
传递给此方法的C#泛型是在编译时确定的,因此T始终是基类,而不是派生类,但是如果在调用{前强制转换为类型object
{1}},该方法将使用WriteRecord
,它将返回派生类型。
GetType()