您的基本问题是 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 的限制:
DynamicType - 使用类型存储附加的Type 信息(默认情况下它包括AssemblyQualifiedName,尽管这可以由用户控制)。这使得序列化弱模型成为可能,即 object 用于属性成员,但是目前这仅限于 contract 类型(不是原语),并且不适用于具有继承的类型(这些限制可能会在以后删除)。与AsReference 一样,它使用了非常不同的布局格式
虽然上面的文档存在于former project site 并且尚未移动到current site,但对于非合约类型的限制在版本 2.0.0.668 中肯定仍然存在。 (我测试了在List<object>中添加int值失败;我没有检查继承的限制是否仍然存在。)