序列化基础 class 属性

Serializing base class properties

所以,如果我有:

  [ProtoContract]
  public abstract class BaseRequest
  {
     [ProtoMember(1)] public Guid Guid { get; set; }
  }

  [ProtoContract]
  public class Request : BaseRequest
  {
     [ProtoMember(1)] public long Id { get; set; }
  }

我尝试序列化 Request 和反序列化 BaseRequest,它不起作用。它不知道具体是什么class。我需要添加一个 [ProtoInclude]。这对我来说很有意义。

我看到的是,如果我序列化 Request 和反序列化 Request,那也不起作用,我认为这是意外的。我希望序列化程序已经知道在这种情况下工作所需的一切。我需要在 BaseRequest 中包含 [ProtoInclude],即使我正在序列化的只是 Request。

我 运行 遇到麻烦的地方是我在库中定义了一个 BaseRequest,而该库的使用者需要继承它。基本上,一种特定类型的请求必须附加数据——除了将继承和 copy/pasting 代码转储到每个子 class 之外,是否有这种模式?

我想出了一个办法,我认为它会奏效,尽管确实感觉应该有更好的方法:

[ProtoContract]
public abstract class BaseRequest
{
   public static int NextSubType = 1000;
   public static ConcurrentDictionary<Type, int> Initialized = new ConcurrentDictionary<Type, int>();
   public static object SyncObject = new object();
 
   [ProtoMember(1)] public Guid Guid { get; set; }

   protected BaseRequest()
   {
      var type = this.GetType();

      if (!Initialized.ContainsKey(type))
      {
         lock (SyncObject)
         {
            if (!Initialized.ContainsKey(type))
            {
               var next = Interlocked.Increment(ref BaseRequest2.NextSubType);
               RuntimeTypeModel.Default.Add(typeof(BaseRequest2), true).AddSubType(next, type);
               Initialized[type] = next;
            }
         }
      }
   }
}

[ProtoContract]
public class Request : BaseRequest
{
   [ProtoMember(1)] public long Id { get; set; }
}

为了让您序列化 Request 和反序列化 BaseRequest 等,它通过从 最基本类型 开始并向更多派生类型工作来实现继承;所以如果这是 xml,它将是:

<BaseType>
    <BaseTypeField1/>
    //...
    <--- at most one, possibly none, of the following -- >
    <SubType1>...</SubType1>
    <SubType2>...</SubType2>
</BaseType>

它需要在第一次尝试接触继承模型中的任何类型时建立对 BaseType 的这种理解。现在,发现您的基类型很容易,但是通过反射发现任何类型的每个可能的派生类型 真的很难 ,因此 ProtoInclude 需要在基类型上,而不是派生类型上。


如果您可以提供可靠、一致的字段编号到子类型的映射,则可以在运行时 而不是 通过 ProtoInclude 配置它,但是:您需要提供并管理您自己的子类型注册表。如果你有这个,我可以告诉你如何更好地配置模型。