我如何为这个特定的类编写自定义的 protobuf-net 序列化器

问题描述 投票:0回答:1

我正在尝试编写一个自定义的 protobuf-net 序列化器,以将

object
类型的属性放入线路中。

[ProtoContract(Serializer=typeof(ChangeRecordSerializer))]
public class ChangeRecord
{
   public object NewValue {get;set;}
}

这就是我现在的位置:

public class ChangeRecordSerializer : ISerializer<ChangeRecord>
{
   public void Write(ref ProtoWriter.State state, ChangeRecord value)
   {
      state.WriteString(1, value.NewValue.GetType().FullName;
      // how to serialize value.NewValue???
   }

   public void Read(ref ProtoReader.State state, ChangeRecord value)
   {
      int num = 0;
      string typeName = null;
      while ((num = state.ReadFieldHeader()) > 0)
      {
         switch (num)
         {
            case 1:
               typeName = state.ReadString();
               break;

            case 2:
               var type = Type.GetType(typeName);
               // how to read value.NewValue???
               break;
         }
      }
   }

   public SerializerFeatures Features => SerializerFeatures.CategoryMessage | SerializerFeatures.WireTypeString;
}

如何实现这两行注释掉的代码?

protobuf-net
1个回答
0
投票

使用自定义序列化器的问题是(至少目前)一旦达到该级别:您需要保持在该级别 - 这意味着:您不能仅仅让序列化器处理所有预期的类型:它期望你从那里向下明确表达,这会变得非常尴尬。如果这是我,我只会使用代理人,让代理人与受歧视的工会“类似”地工作。这不需要很昂贵;考虑: using ProtoBuf; Show(32); Show("abc"); Show(new Foo { Bar = "banana" }); static void Show(object value) { var obj = new ChangeRecord { NewValue = value }; var clone = Serializer.DeepClone(obj); Console.WriteLine($"{obj.NewValue} => {clone.NewValue}"); } [ProtoContract(Surrogate = typeof(ChangeRecordSurrogate))] public class ChangeRecord { public object? NewValue { get; set; } } [ProtoContract] public class Foo { [ProtoMember(1)] public string? Bar { get; set; } public override string ToString() => $"Foo: {Bar}"; } [ProtoContract] struct ChangeRecordSurrogate { public static implicit operator ChangeRecordSurrogate(ChangeRecord value) => new ChangeRecordSurrogate { Value = value?.NewValue }; public static implicit operator ChangeRecord(ChangeRecordSurrogate value) => new ChangeRecord { NewValue = value.Value! }; public object? Value { get; set; } [ProtoMember(1)] public int? ValueInt32 { get => Value is int x ? x : default; set => Value = value; } [ProtoMember(2)] public string? ValueString { get => Value as string; set => Value = value; } [ProtoMember(3)] public Foo? ValueFoo { get => Value as Foo; set => Value = value; } }

© www.soinside.com 2019 - 2024. All rights reserved.