我想将Vector3对象(参见https://docs.unity3d.com/ScriptReference/Vector3.html)写入CSV文件,它是我自定义类的一部分:
public class BehaviouralData
{
public float ActionZ { get; set; }
public float ActionX { get; set; }
public int TargetBallAgentHashCode { get; set; }
public Vector3 TargetBallLocalPosition { get; set; }
public bool CollectBehaviouralData { get; set; }
public DateTime ActionTime { get; set; }
public DateTime Time { get; set; }
}
字符串
因此我使用ClassMap
public sealed class Vector3Map : ClassMap<Vector3>
{
public Vector3Map()
{
Map(m => m.x);
Map(m => m.y);
Map(m => m.z);
}
}
型
我在写入文件之前注册:
...
using (var csv = new CsvWriter(writer, config))
{
csv.Context.RegisterClassMap<Vector3Map>();
csv.WriteRecords(data);
}
...
型
当我尝试保存文件时,收到以下错误消息:
ArgumentException: Incorrect number of arguments supplied for call to method 'Single get_Item(Int32)'
Parameter name: property
System.Linq.Expressions.Expression.Property (System.Linq.Expressions.Expression expression, System.Reflection.PropertyInfo property) (at <1e18c5a6594041c9844bfd0b6618ee4a>:0)
CsvHelper.Expressions.ExpressionManager.CreateGetMemberExpression (System.Linq.Expressions.Expression recordExpression, CsvHelper.Configuration.ClassMap mapping, CsvHelper.Configuration.MemberMap memberMap) (at <9a1379e089274cc1baf4edcf480e4c6d>:0)
CsvHelper.Expressions.ExpressionManager.CreateGetMemberExpression (System.Linq.Expressions.Expression recordExpression, CsvHelper.Configuration.ClassMap mapping, CsvHelper.Configuration.MemberMap memberMap) (at <9a1379e089274cc1baf4edcf480e4c6d>:0)
CsvHelper.Expressions.ObjectRecordWriter.CreateWriteDelegate[T] (T record) (at <9a1379e089274cc1baf4edcf480e4c6d>:0)
CsvHelper.Expressions.RecordWriter.GetWriteDelegate[T] (T record) (at <9a1379e089274cc1baf4edcf480e4c6d>:0)
CsvHelper.Expressions.RecordWriter.Write[T] (T record) (at <9a1379e089274cc1baf4edcf480e4c6d>:0)
CsvHelper.Expressions.RecordManager.Write[T] (T record) (at <9a1379e089274cc1baf4edcf480e4c6d>:0)
CsvHelper.CsvWriter.WriteRecords[T] (System.Collections.Generic.IEnumerable`1[T] records) (at <9a1379e089274cc1baf4edcf480e4c6d>:0)
Rethrow as WriterException: An unexpected error occurred.
IWriter state:
Row: 2
Index: 0
HeaderRecord:
2
CsvHelper.CsvWriter.WriteRecords[T] (System.Collections.Generic.IEnumerable`1[T] records) (at <9a1379e089274cc1baf4edcf480e4c6d>:0)
Util.SaveDataToCSV[T] (System.String path, System.Collections.Generic.List`1[T] data) (at Assets/Scripts/Util/Util.cs:178)
BehaviourMeasurement.SaveRawBehavioralDataToCSV () (at Assets/Scripts/Measurement/BehaviourMeasurementBehaviour.cs:1021)
BehaviourMeasurementBehaviour.OnDisable () (at Assets/Scripts/Measurement/BehaviourMeasurementBehaviour.cs:122)
型
空CSV文件包含以下列:
ActionZ,ActionX,TargetBallAgentHashCode,Item,Item,magnitude,sqrMagnitude,magnitude,sqrMagnitude,CollectBehaviouralData,ActionTime,Time
型
正如你所看到的,并不是坐标被写入文件,而是其他属性(例如magnitude
)我不想包括在内。为什么CSVHelper不能将正确的属性Map到CSV文件中?
2条答案
按热度按时间i86rm4rw1#
我在.Net Fiddle里玩了一会儿。
当对
BehaviouralData
也使用显式Map时字符串
好像是修好了。
使用自动Map时,如
型
这可能是默认情况下无论如何都要使用的-它又坏了。
我也试过了,但还是一样。
型
实际上这个显式Map也不起作用-_-
它只将
Vector3
打印到CSV中,因此第二个Map似乎完全被忽略。很可怕但这个好像有用
型
但说实话,至少对于作家来说,这似乎非常明确,充其量只是一个变通办法。
kmpatx3s2#
您的基本问题是,正如derHugo在answer中指出的那样,当CsvHelper自动Map一个类型时,它会自动Map所有属性值的类型,而不是使用以前可能为这些类型注册的任何类Map。特别是在
Vector3
的情况下,它自动Map其属性,而不是字段x
,y
和z
,最终导致崩溃。那么,你的解决方法是什么?除了像derHugo的回答中建议的那样手动Map
x
、y
和z
字段之外,还有几个额外的选项。首先,您可以自动Map包含
Vector3
的类型,然后修复引用。为此,请定义以下泛型ClassMap<T>
和关联的扩展方法:字符串
现在序列化
BehaviouralData
,如下所示:型
其结果是:
型
如果您希望
x
、y
和z
字段有一些前缀,请将[HeaderPrefix("prefix")]
添加到TargetBallLocalPosition
,如下所示:型
你会得到:
型
如果您需要对
BehaviouralData
的格式进行更多的手动控制,则需要创建一个手动类Map。当你这样做时,使用方法ClassMap<TClass>.References<TClassMap>(Expression<Func<TClass, object>> expression, params object[])
而不是ClassMap<TClass>.Map()
来引用Vector3
的内容,使用你的Vector3Map
:型
演示小提琴here。
[1]CsvHelper似乎有一个bug。具体来说,对于没有实现
IEnumerable
的类,它会尝试自动Map**indexed properties**,导致您看到的异常。这是CsvHelper中的一个简单的错误,它应该在自动Map反射发现的任何属性之前检查PropertyInfo.GetIndexParameters().Length == 0
。但是即使CsvHelper修复了这个bug,您仍然无法得到您想要的东西,也就是Vector3
的三个字段,而不是它的属性。