在C#中使用Tuple键反序列化字符串

时间:2018-02-09 23:37:01

标签: c# .net serialization

我有这样的字典:

var dict1 = new Dictionary<(int, int), int);
dict1.add((1,2), 3);

使用以下命令将其序列化为字符串:

var s = JsonConvert.SerializeObject(dict1);
// s = "{\"(1,2)\":\"3\"}";

尝试使用以下命令反序列化字符串时使用:

var j = JsonConvert.DeserializeObject<Dictionary<(int, int), int>>(s);

我收到如下错误:

  

'无法将字符串'(1,2)'转换为字典键类型'System.ValueTuple`2 [System.Int32,System.Int32]'。创建一个TypeConverter以从字符串转换为键类型对象。

如何将字符串反序列化为元组键?使用自定义对象或TypeConverter?如果是这样,怎么样?

1 个答案:

答案 0 :(得分:4)

首先,你自己为ValueTuples的TypeConverter&lt; T1,T2&gt;

internal class ValueTupleConverter<T1, T2>
   : TypeConverter 
   where T1: struct where T2: struct
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, 
      Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context,
      CultureInfo culture, object value)
    {
        var elements = ((String)value).Split(new[] { '(', ',', ')'},
          StringSplitOptions.RemoveEmptyEntries);

        return (
            JsonConvert.DeserializeObject<T1>(elements.First()), 
            JsonConvert.DeserializeObject<T2>(elements.Last()));
    }
}

(应该使生产代码更加健壮和高效。)

然后,因为您无法在编译时执行通常的应用TypeConverter属性,所以在运行时添加它,一次

  TypeDescriptor.AddAttributes(typeof((Int32, Int32)), 
    new TypeConverterAttribute(typeof(ValueTupleConverter<Int32, Int32>)));

最后,你正在进行转换

var j = JsonConvert.DeserializeObject<Dictionary<(int, int), int>>(s);