之前
使用JsonConverterAttribute
,我們可以為任意類型自定義 Json 序列化。例如:
[JsonConverter(typeof(UserJsonConverter))]
public?class?User
{public?string?Name?{?get;?set;?}public?override?string?ToString(){return?Name;}
}public?class?UserJsonConverter?:?JsonConverter<User>
{public?override?User??Read(ref?Utf8JsonReader?reader,?Type?typeToConvert,?JsonSerializerOptions?options){//演示代碼,不實現具體序列化邏輯reader.Read();return?new?User?{?Name?=?"MyIO"?};}
}
反序列時將返回UserConverter
生成的 User 實例:
var?user?=?JsonSerializer.Deserialize<User>("{}");
但這不是本文的重點。重點是UserJsonConverter
如何被實例化的。
查看JsonConverterAttribute
的源碼,JsonConverter
的類型在構造函數中賦值給了ConverterType
屬性:
public?class?JsonConverterAttribute?:?JsonAttribute
{public?JsonConverterAttribute(Type?converterType){ConverterType?=?converterType;}?public?Type??ConverterType?{?get;?private?set;?}
}
而ConverterType
的使用代碼如下:
JsonConverter??converter;Type??type?=?converterAttribute.ConverterType;
if?(type?==?null)
{converter?=?converterAttribute.CreateConverter(typeToConvert);
}
else
{converter?=?(JsonConverter)Activator.CreateInstance(type)!;
}
也就是說,JsonConverte
實例是通過反射(Activator.CreateInstance(type)
)生成的。
一般來說,反射的執行效率較低,這時我們注意到if
分支,可以用CreateConverter
方法創建實例。
修改實現代碼如下:
public?class?UserJsonConverterAttribute?:?JsonConverterAttribute
{public?override?JsonConverter??CreateConverter(Type?typeToConvert){return?new?UserJsonConverter();}
}[UserJsonConverterAttribute()]
public?class?User
同樣可以反序列成功,這時使用的是強類型的JsonConverter。
但是,這種方式也有一個缺點,每當我們實現了一個xxJsonConverter
,就需要再定義一個xxJsonConverterAttribute
。
而我們的目的,只是為了創建 JsonConverter 實例,代碼邏輯相同,完全可以用范型方式實現。
但是在 C# 11 之前,是不支持這樣定義的。
C# 11
在 C# 11 中,可以聲明基類為System.Attribute
的泛型類。
這樣,上面的代碼可以改造為如下形式:
public?class?GenericJsonConverterAttribute<T>?:?JsonConverterAttribute?where?T?:?JsonConverter,?new()
{public?override?JsonConverter??CreateConverter(Type?typeToConvert){return?new?T();}
}[GenericJsonConverter<UserJsonConverter>]
public?class?User[GenericJsonConverter<OrderJsonConverter>]
public?class?Order
添加微信號【MyIO666】,邀你加入技術交流群