如何使用Parquet.net序列化包含接口类型成员的类型?
使用Parquet.net序列化含接口成员的类型问题
使用Parquet.net时,能否序列化包含接口类型成员的类型?我在MakeField方法中遇到了NotImplementedException异常。
代码示例:
using Parquet.Serialization; //using MemoryStream stream = new(); //await ParquetSerializer.SerializeAsync([new LineOK ()], stream); using MemoryStream stream = new(); await ParquetSerializer.SerializeAsync([new LineKO()], stream); interface IPoint { decimal X { get; set; } decimal Y { get; set; } } class Point : IPoint { public decimal X { get; set; } public decimal Y { get; set; } } class LineOK { public Point Start { get; } = new(); public Point End { get; } = new(); } class LineKO { public IPoint Start { get; } = new Point(); public IPoint End { get; } = new Point(); }
我明白问题根源:对象集合里可能存在不同的接口实现,会导致Parquet的列/架构不一致。但如果数据集里只有一种实现,有没有办法强制序列化?
如果不行,还有哪些可选方案?比如用专用DTO:
using MemoryStream stream = new(); await ParquetSerializer.SerializeAsync([new LineDto(new LineKO())], stream); class LineDto { public Point Start { get; } public Point End { get; } public LineDto(LineKO lineKo) { Start = (Point)lineKo.Start; End = (Point)lineKo.End; } }
回答
核心结论
Parquet.net的默认序列化器不支持直接序列化接口类型成员。Parquet是强Schema的列存储格式,接口本身无法提供固定的列结构定义,因此MakeField方法会抛出NotImplementedException。即便数据集只有一种接口实现,默认序列化逻辑也不会自动推断具体类型。
可行解决方案
1. 专用DTO(推荐)
这是最直接可靠的方案,通过定义DTO将接口类型转换为具体实现类,完全适配Parquet的强Schema要求,代码逻辑清晰且易于维护,就是你提到的实现方式。
2. 序列化前强制转换类型
无需额外定义DTO,在序列化前将接口成员转换为具体实现类,再传入序列化方法:
var targetLines = new List<LineKO> { new LineKO() }; var serializableLines = targetLines.Select(l => new { Start = (Point)l.Start, End = (Point)l.End }).ToList(); using MemoryStream stream = new(); await ParquetSerializer.SerializeAsync(serializableLines, stream);
3. 自定义序列化扩展
如果需要更灵活的处理,可以实现Parquet.net的自定义序列化扩展(比如IParquetSerializer或类型转换器),手动指定接口对应的具体实现类型。不过这种方式需要深入框架的扩展点,实现复杂度较高,适合有特殊需求的场景。
内容的提问来源于stack exchange,提问作者Pragmateek
相关产品推荐
相关产品推荐

