你的基本问题是DynamicType = true
仅适用于该特定属性,并且仅序列化该特定属性的值的类型信息。它不会递归地应用于该对象包含的任何属性。然而,你的object
值嵌套在容器的多个级别中:
public Dictionary<ContextActions, List<Tuple<string, List<object>>>> Value;
您需要做的是序列化每个的类型信息object
在这个列表元组字典中。您可以通过引入代理值类型来做到这一点:
[ProtoContract]
public struct DynamicTypeSurrogate<T>
{
[ProtoMember(1, DynamicType = true)]
public T Value { get; set; }
}
public static class DynamicTypeSurrogateExtensions
{
public static List<DynamicTypeSurrogate<T>> ToSurrogateList<T>(this IList<T> list)
{
if (list == null)
return null;
return list.Select(i => new DynamicTypeSurrogate<T> { Value = i }).ToList();
}
public static List<T> FromSurrogateList<T>(this IList<DynamicTypeSurrogate<T>> list)
{
if (list == null)
return null;
return list.Select(i => i.Value).ToList();
}
}
然后修改你的RedisDataObject
按如下方式序列化代理字典:
[ProtoContract]
public class RedisDataObject
{
[ProtoMember(1)]
public string DataHash;
[ProtoIgnore]
public Dictionary<ContextActions, List<Tuple<string, List<object>>>> Value;
[ProtoMember(2)]
private Dictionary<ContextActions, List<Tuple<string, List<DynamicTypeSurrogate<object>>>>> SurrogateValue
{
get
{
if (Value == null)
return null;
var dictionary = Value.ToDictionary(
p => p.Key,
p => (p.Value == null ? null : p.Value.Select(i => Tuple.Create(i.Item1, i.Item2.ToSurrogateList())).ToList()));
return dictionary;
}
set
{
if (value == null)
Value = null;
else
{
Value = value.ToDictionary(
p => p.Key,
p => (p.Value == null ? null : p.Value.Select(i => Tuple.Create(i.Item1, i.Item2.FromSurrogateList())).ToList()));
}
}
}
}
另请注意以下限制DynamicType
提及here https://code.google.com/archive/p/protobuf-net/wikis/Attributes.wiki:
DynamicType
- 存储额外的Type
类型信息(默认情况下它包括AssemblyQualifiedName
,尽管这可以由用户控制)。这使得序列化弱模型成为可能,即object
用于财产成员,但目前仅限于contract类型(不是基元),并且不适用于具有继承的类型(这些限制可能稍后会被删除)。喜欢与AsReference
,这使用了非常不同的布局格式
虽然上述文档存在于原项目工地 https://code.google.com/archive/p/protobuf-net/并且还没有被移动到当前站点 https://github.com/mgravell/protobuf-net/wiki,从 2.0.0.668 版本开始,对非合约类型的限制肯定仍然存在。 (我测试了添加一个int
的价值List<object>
失败;我没有检查继承的限制是否仍然存在。)