覆盖每个属性序列化的内容

时间:2014-05-22 08:52:56

标签: c# protobuf-net

1)

我正在使用protobuf-net通过网络同步两个对象,因为我能够跟踪两个同步之间的变化,我只能发送更改的内容而不是整个对象。

所以基本上我想基于'脏'标志覆盖所有可空属性序列化。

这样做有“好”的方法吗? (我可以使用一个线程本地bool修改我的属性getter的行为,但是......)。

2)(奖金问题)

我继续序列化“真实”对象或通用DTO对象。但是我被困在DTO上,我通常想要序列化<int, object>的KVP,这将是属性id及其数据,例如,它可以像Dictionary<string, Hashset<int>>那样复杂,protobuf-net如果您知道类型,则传输得很好,但如果它被声明为对象则不能传输。

如果我处理由基本类型组成的嵌套泛型集合,我会欣赏一些建议,我在网上看到2)似乎是一个死胡同。 1)如果我可以改变行为,可以正常工作,但是,DTO本来是完美的,因为它满足了传输变化的需要,而不是“完整对象”......

2 个答案:

答案 0 :(得分:1)

protobuf-net支持标准ShouldSerialize*模式;因此,对于属性Foo,您可以添加:

private bool ShouldSerializeFoo() {
    return /* true to serialize, false to omit */
}

请注意,在某些平台上,由于元编程/反射权限,该方法必须为public。另请注意,对于 nullable 属性,如果您不希望序列化它们,也可以返回null

我真的不明白你的第二个问题是什么;你能澄清一下吗?

答案 1 :(得分:1)

回复:#2红利问题

我不完全理解,但部分内容与我实施的serializing obfuscated Types问题的解决方法非常相似。该解决方案还允许一种序列化PointSizeFontImage等内容的方法。

我使用的“技巧”不是序列化类类型,而是将原始属性类型和字符串值提取到TypeValue对原语。它们存储为Dictionary<T, TypeValuePair>,可用于重建类对象。 Protobuf-net,然后只需序列化常规字典。

某些类类型的结果可能是Dictionary<String, <Dictionary<T, TypeValuePair>>,听起来与您提到的类似。你最终会进行类型转换,但这并不困难(VB,因为我不能在快速或快速的情况下编写C#):

' from TVP ctor
Sub New(v As Object)       ' thing to convert
    ' convert whatever to string:
    Dim conv As TypeConverter = TypeDescriptor.GetConverter(v.GetType)

    _value = conv.ConvertToInvariantString(v)
    ...

   ' original type is stored as an enum  (eg GenericTypes.Font)
   _type = GenericConverter.GetGenericTypeCode(v)
End Sub

还有一点,像EnumBitmap这样的一些事情必须以不同的方式处理,但只是略有不同。为您的类/类型创建这些类的集合,并将 提交给ProtoBuf。


我将进程拆分为将字符串属性值转换回正确的类型。 TVP进行实际转换,但消费者进行转换。 TVP的TValue属性重新创建原始数据类型,但返回一个Object:

   Public ReadOnly Property TValue As Object
      Get
         Dim R As Object = Nothing

         Select Case _type
             Case GenericTypes.TInt32
                R = Int32.Parse(_value) 

            Case GenericTypes.TFont
                R = TypeDescriptor.GetConverter(GetType(System.Drawing.Font)) _
                          .ConvertFromInvariantString(_value)

            Case etc
         End Select

         Return R
      End Get
    End Property

我有一个容纳Dictionary<T, TypeValuePair>的课程并提供类似这样的功能:

    Public Function GetTItem(Of TT)(key As T) As TT
        If _col.ContainsKey(key) Then
            ' cast the object return to requested Type (TT)
            Return CType(_col(key).TValue, TT)
        Else
            Return Nothing
        End If
    End Function

T只是T中的Dictionary<T, TypeValuePair>,允许集合使用字符串或int键。如果您愿意,可以将TT传递给TValueGetTItem通过原始类将其强制转换为请求的类型,该类知道其自身属性的类型,因此没有可疑的假设:

' get item enum.N and cast to Int32:
_ziggys = myThing.GetTItem(Of Int32)(PropIndexEnum.Ziggys)

正如我所说,我不确定这会有所帮助,但你的情况听起来很熟悉。您要序列化的任何类对象都需要能够以可序列化的形式咳出其组成属性,而不是尝试将Object提交给序列化程序。当然,这是在高容量情况下可能过多的所有开销,但它可以工作。