对象(通用)的 Protobuf-net 序列化抛出错误 No serializer defined for type: System.Object
Protobuf-net serialization of object (generic) throws error No serializer defined for type: System.Object
如何使用 Protobuf 序列化一个 generic(T) 对象,它可以保存任何类型的数据 (int / string / DateTime) -网。以下是我的代码
[ProtoContract]
public class E1DataRow
{
[ProtoMember(1)]
public List<NameValue> NameValues { get; set; }
public E1DataRow()
{
NameValues = new List<NameValue>();
}
public void AddNameValue(string name, object obj, Type type)
{
NameValues.Add(new NameValue { Name = name, Value = obj, ValueType = type });
}
}
[ProtoContract]
public class NameValue
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public object Value { get; set; }
[ProtoMember(3)]
public Type ValueType { get; set; }
}
连载码
var e1DataRows = new List<E1DataRow>();
/*
Code to add Data rows to e1DataRows
e1DataRow.AddNameValue(column.ColumnName, value, column.TypeOfColumn);
*/
using (var stream = File.OpenWrite(path))
{
Serializer.Serialize(stream, e1DataRows);
}
[ProtoMember(2, DynamicType = true)]
public object Value { get; set; }
以上代码抛出以下错误 (DynamicType = true)
ProtoMemberAttribute.DynamicType' is obsolete: 'Reference-tracking and dynamic-type are not currently implemented in this build;他们可能会在以后恢复;这部分是由于怀疑这些功能是否可取,部分是由于对测试所有场景的信心过高(这需要时间;那个时间还没有发生);邀请反馈'
如果您能帮助解决如何使用 Protobug-net 序列化列表的问题,那就太好了。谢谢...
如果在 c# >= 4 上,您可能想尝试以下操作:
[ProtoContract]
public class E1DataRow
{
[ProtoMember(1)]
public List<NameValue<dynamic>> NameValues { get; set; }
public E1DataRow()
{
NameValues = new List<NameValue<dynamic>>();
}
public void AddNameValue(string name, dynamic obj)
{
NameValues.Add(new NameValue<dynamic> { Name = name, Value = obj });
}
}
public class NameValue<T>
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public T Value { get; set; }
[ProtoMember(3)]
public Type ValueType { get { return Value.GetType(); } }
}
不确定 Protobuf-net 是否喜欢 List<NameValue<dynamic>>
,目前无法测试。
ProtoMember(3)
在 ValueType
可能不是必需的,因为无论如何都是只读的。
您可能想看看 https://github.com/dotarj/protobuf-net-data - 这与 protobuf-net 无关(不同的作者等),但它 使用 protobuf-net 来执行DataTable
和数据读取器的序列化,因此它 可能 做你想做的现成的。
至于自己实现:
protobuf-net 从根本上不支持 object
(或 dynamic
,这只是一种奇特的拼写方式 object
)。有一些方法可以解决这个问题,本质上类似于 protobuf 中的 oneof
处理 - 即类似于(在 protobuf 术语中):
message Foo {
oneof payload {
string payload_string = 1;
bool payload_bool = 2;
int32 payload_int32 = 3;
float payload_float = 4;
// etc
}
}
由于“条件序列化”,这很容易在 protobuf-net 中组合在一起,这意味着您可以执行以下操作:
public object Value { get; set; }
[ProtoMember(1)]
public string ValueString
{
get => (string)Value;
set => Value = value;
}
public bool ShouldSerializeValueString()
=> Value is string;
[ProtoMember(2)]
public string ValueBoolean
{
get => (bool)Value;
set => Value = value;
}
public bool ShouldSerializeValueBoolean()
=> Value is string;
// etc
如何使用 Protobuf 序列化一个 generic(T) 对象,它可以保存任何类型的数据 (int / string / DateTime) -网。以下是我的代码
[ProtoContract]
public class E1DataRow
{
[ProtoMember(1)]
public List<NameValue> NameValues { get; set; }
public E1DataRow()
{
NameValues = new List<NameValue>();
}
public void AddNameValue(string name, object obj, Type type)
{
NameValues.Add(new NameValue { Name = name, Value = obj, ValueType = type });
}
}
[ProtoContract]
public class NameValue
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public object Value { get; set; }
[ProtoMember(3)]
public Type ValueType { get; set; }
}
连载码
var e1DataRows = new List<E1DataRow>();
/*
Code to add Data rows to e1DataRows
e1DataRow.AddNameValue(column.ColumnName, value, column.TypeOfColumn);
*/
using (var stream = File.OpenWrite(path))
{
Serializer.Serialize(stream, e1DataRows);
}
[ProtoMember(2, DynamicType = true)]
public object Value { get; set; }
以上代码抛出以下错误 (DynamicType = true) ProtoMemberAttribute.DynamicType' is obsolete: 'Reference-tracking and dynamic-type are not currently implemented in this build;他们可能会在以后恢复;这部分是由于怀疑这些功能是否可取,部分是由于对测试所有场景的信心过高(这需要时间;那个时间还没有发生);邀请反馈'
如果您能帮助解决如何使用 Protobug-net 序列化列表的问题,那就太好了。谢谢...
如果在 c# >= 4 上,您可能想尝试以下操作:
[ProtoContract]
public class E1DataRow
{
[ProtoMember(1)]
public List<NameValue<dynamic>> NameValues { get; set; }
public E1DataRow()
{
NameValues = new List<NameValue<dynamic>>();
}
public void AddNameValue(string name, dynamic obj)
{
NameValues.Add(new NameValue<dynamic> { Name = name, Value = obj });
}
}
public class NameValue<T>
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public T Value { get; set; }
[ProtoMember(3)]
public Type ValueType { get { return Value.GetType(); } }
}
不确定 Protobuf-net 是否喜欢 List<NameValue<dynamic>>
,目前无法测试。
ProtoMember(3)
在 ValueType
可能不是必需的,因为无论如何都是只读的。
您可能想看看 https://github.com/dotarj/protobuf-net-data - 这与 protobuf-net 无关(不同的作者等),但它 使用 protobuf-net 来执行DataTable
和数据读取器的序列化,因此它 可能 做你想做的现成的。
至于自己实现:
protobuf-net 从根本上不支持 object
(或 dynamic
,这只是一种奇特的拼写方式 object
)。有一些方法可以解决这个问题,本质上类似于 protobuf 中的 oneof
处理 - 即类似于(在 protobuf 术语中):
message Foo {
oneof payload {
string payload_string = 1;
bool payload_bool = 2;
int32 payload_int32 = 3;
float payload_float = 4;
// etc
}
}
由于“条件序列化”,这很容易在 protobuf-net 中组合在一起,这意味着您可以执行以下操作:
public object Value { get; set; }
[ProtoMember(1)]
public string ValueString
{
get => (string)Value;
set => Value = value;
}
public bool ShouldSerializeValueString()
=> Value is string;
[ProtoMember(2)]
public string ValueBoolean
{
get => (bool)Value;
set => Value = value;
}
public bool ShouldSerializeValueBoolean()
=> Value is string;
// etc