起源:https://note.guoqianfan.com/2…
前言
有时咱们会遇到这么一种状况:在json数据里,数组里的数据类型不统一,导致咱们不能间接反序列化为指标类型。最终咱们只能反序列化为JObject类型,而后通过字符串取值的形式来取出数据。
上面介绍一种新形式:通过自定义隐式转换,把不一样的数据类型反序列化为一样的数据类型。
基础知识
类型转换有2种:隐式转换和显式转换。然而,不论是隐式转换,还是显式转换,都是生成了一个新对象返回的。扭转新对象的属性,不会影响老对象!(dynamic对象
除外,详情搜寻dynamic动静类型
。)
自定义隐式/显式转换的办法须要用到几个关键字:implicit
(隐式转换)、explicit
(显式转换)、operator(操作符)
。更多的留神点见下:
- 办法必須是static
- 应用
implicit
或explicit
- 搭配
operator
(此也是c#關鍵字,可在類別或結構宣告內多載內建運算子或提供使用者定義的轉換) - 返回值为要转换为的指标类型,但不要在办法上申明,办法名为指标类型。留神:返回值不肯定是本类类型。本类型和其余类型之间能够相互转换,只有定义转换方法就行。
- 参数为原始类型,办法名为指标类型
- 类A到类B的类型转换定义不能在类C中进行(即2个类的转换不能在第3个类中定义),否则会报错:
用户定义的转换必须是转换成关闭类型,或者从关闭类型转换
。具体查看前面的用户定义的转换必须是转换成关闭类型,或者从关闭类型转换 - 不能被
virtual
/override
润饰(不能“笼罩”运算符,因为它们是动态的。)Overriding implicit operators in C#
示例代码
//================定义类型和办法================
class Robot
{
public int Id { get; set; }
public string Name { get; set; }
public Robot(int id, string name)
{
Id = id;
Name = name;
}
#region 其余类型->本类
//隐式转换
public static implicit operator Robot(string name)
{
return new Robot(101, name);
}
//显式转换
public static explicit operator Robot(int id)
{
return new Robot(id, "miku");
}
#endregion
#region 本类->其余类型
//隐式转换
public static implicit operator string(Robot robot)
{
return robot.Name;
}
//显式转换
public static explicit operator int(Robot robot)
{
return robot.Id;
}
#endregion
}
//================测试代码================
#region 其余类型->本类
string gumiStr = "gumi";
Robot gumi001 = gumiStr; //隐式转换
Console.WriteLine("隐式转换:gumi001 : {0}", JsonConvert.SerializeObject(gumi001));
int lukaId = 1004;
Robot luka001 = (Robot)lukaId; //显式转换
Console.WriteLine("显式转换:luka001 : {0}", JsonConvert.SerializeObject(luka001));
#endregion
#region 其余类型->本类
Robot miku001 = new Robot(1001, "miku10001");
//隐式转换
string mikuName = miku001;
//显式转换
int mikuId = (int)miku001;
Console.WriteLine("隐式转换:miku001 Name: {0}", mikuName);
Console.WriteLine("显式转换:miku001 Id: {0}", mikuId);
#endregion
输入后果如下:
隐式转换:gumi001 : {"Id":101,"Name":"gumi"}
显式转换:luka001 : {"Id":1004,"Name":"miku"}
隐式转换:miku001 Name: miku10001
显式转换:miku001 Id: 1001
理论利用
问题
[1,[[2,2],[2,2],[2,2],[2,2]]]
这样一个字符串,如何能够反序列化成一个对象?(如何定义这个类?)
答案
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
var json = "[1,[[2,2],[2,2],[2,2],[2,2]]]";
var root = JsonConvert.DeserializeObject<Root>(json);
foreach(var ele in root)
{
if(ele.SingleValue.HasValue)
{//有值,原始数据为 1
Console.WriteLine(ele.SingleValue.Value);
}else
{//原始数据为 二维数组
Console.WriteLine(string.Join(" ",ele.Select(x=>string.Join(",",x))));
}
}
Console.WriteLine(JsonConvert.SerializeObject(root));
}
}
class Root : List<Element> { }
[JsonConverter(typeof(CConverter))]
class Element : List<List<long>>
{
//该属性,寄存 1 。后续能够通过判断该属性是否有值来得悉原始数据的状况
public long? SingleValue { get; set; }
//遇到 1 ,隐式转换为 该类型,其中 1 被寄存到SingleValue属性
public static implicit operator Element(long d)
{
return new Element { SingleValue = d };
}
}
public class CConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Element));
}
public override bool CanRead { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var ele = value as Element;
var token = ele.SingleValue.HasValue ? JToken.FromObject(ele.SingleValue.Value) : JToken.FromObject(ele.ToList());
token.WriteTo(writer);
}
public override bool CanWrite { get { return true; } }
}
报错
用户定义的转换必须是转换成关闭类型,或者从关闭类型转换
这个谬误,与关闭类型无关。
是因为有这个限度:类A到类B的类型转换定义不能在类C中进行(即2个类的转换不能在第3个类中定义)
所以对于指标类型是汇合类List<T>
,咱们无奈间接定义到它的转换。不过,有2个曲折的办法:
- 创立个类继承自汇合类
List<T>
,定义到这个子类的转换。下面理论利用中的代码就是这样做的:class Element : List<List<long>>
- 创立
T1
到T2
的自定义转换,应用时一一转换:list.Select(p=>(B)p).ToList()
。
参考
- 隐式转换:用户定义的转换必须是转换成关闭类型,或者从关闭类型转换:https://blog.csdn.net/kamui_s…
其余
利用和设计
在定義類別時,如果有须要,就能够应用這兩個關鍵字來提供類別一些額外的性能
但在应用時也必須考慮設計上是否正当
例如當兩類別有相關性時是否該提取出父类或是接口來应用,而不是為了不便做了一堆轉換,導致程式撰寫與維護上的困難。
读音
- 隐式转换:
implicit
[ɪmˈplɪsɪt] adj.不言明[宛转]的; 无疑问的,相对的; 成为一部份的; 内含的; - 显式转换:
explicit
[ɪkˈsplɪsɪt] adj.明确的,分明的; 婉言的; 详述的; 不瞒哄的;
参考
- 【问】这样一个字符串如何反序列化:http://www.newsmth.net/nForum…
- 型別轉換關鍵字explicit與implicit的用法:https://dotblogs.com.tw/lasts…
- c#关键词implicit和explicit:https://blog.csdn.net/Joyhen/…
发表回复