在Converters
和ReadJson
调用期间,转换器可以修改序列化程序的WriteJson
属性,并且在嵌套序列化和反序列化过程中尊重新集合的内容。
这样,我们可以制作一个将指定的转换器临时添加到Converters
属性的转换器,如下所示:
public abstract class CascadeJsonConverterBase : JsonConverter
{
private readonly JsonConverter[] augmentConverters;
protected CascadeJsonConverterBase() : this(new JsonConverter[0]) { }
// this constructor is intended for use with JsonConverterAttribute
protected CascadeJsonConverterBase(object[] augmentConverters)
: this(augmentConverters.Select(FromAttributeData).ToArray())
{ }
protected CascadeJsonConverterBase(JsonConverter[] augmentConverters)
{
this.augmentConverters = augmentConverters;
}
protected static JsonConverter FromAttributeData(object augmentConverterObj)
{
if (!(augmentConverterObj is object[] augmentConverter))
{
throw new ArgumentException($"Each augment converter data should be an object array",nameof(augmentConverters));
}
if (augmentConverter.Length < 1)
{
throw new ArgumentException($"Augment converter data should include at least one item",nameof(augmentConverters));
}
object augmentConverterType = augmentConverter[0];
if (!(augmentConverterType is Type convType))
{
throw new ArgumentException($"Augment converter data should start with its type",nameof(augmentConverters));
}
if (!typeof(JsonConverter).IsAssignableFrom(convType))
{
throw new ArgumentException($"Augment converter type should inherit from JsonConverter abstract type",nameof(augmentConverters));
}
object converter = Activator.CreateInstance(convType,augmentConverter.SubArray(1,augmentConverter.Length - 1));
return (JsonConverter)converter;
}
protected abstract void WriteJsonInner(JsonWriter writer,object value,JsonSerializer serializer);
protected abstract object ReadJsonInner(JsonReader reader,Type objectType,object existingValue,JsonSerializer serializer);
public override void WriteJson(JsonWriter writer,JsonSerializer serializer)
{
using (AugmentedConverterScope(serializer))
{
WriteJsonInner(writer,value,serializer);
}
}
public override object ReadJson(JsonReader reader,JsonSerializer serializer)
{
using (AugmentedConverterScope(serializer))
{
return ReadJsonInner(reader,objectType,existingValue,serializer);
}
}
private AugmentedConverterScopeMgr AugmentedConverterScope(JsonSerializer serializer)
{
// add augmented converters
for (int i = augmentConverters.Length - 1; i >= 0; i--)
{
serializer.Converters.Insert(0,augmentConverters[i]);
}
return new AugmentedConverterScopeMgr(serializer,augmentConverters.Length);
}
private class AugmentedConverterScopeMgr : IDisposable
{
private readonly JsonSerializer serializer;
private readonly int converterCount;
public AugmentedConverterScopeMgr(JsonSerializer serializer,int converterCount)
{
this.serializer = serializer;
this.converterCount = converterCount;
}
public void Dispose()
{
// remove augmented converters
for (int i = 0; i < converterCount; i++)
{
serializer.Converters.RemoveAt(0);
}
}
}
}
然后创建一个转换器,该转换器包装另一个转换器的逻辑,如下所示:
public class CascadeJsonConverter : CascadeJsonConverterBase
{
private readonly JsonConverter wrappedConverter;
public CascadeJsonConverter(Type wrappedConverterType,object[] wrappedConvConstructorArgs,object[] augmentConverters)
: this(CreateConverter(wrappedConverterType,wrappedConvConstructorArgs),augmentConverters.Select(FromAttributeData).ToArray())
{ }
public CascadeJsonConverter(JsonConverter wrappedConverter,JsonConverter[] augmentConverters)
: base(augmentConverters)
{
this.wrappedConverter = wrappedConverter;
}
private static JsonConverter CreateConverter(Type converterType,object[] convConstructorArgs)
{
if (!typeof(JsonConverter).IsAssignableFrom(converterType))
{
throw new ArgumentException($"Converter type should inherit from JsonConverter abstract type",nameof(converterType));
}
return (JsonConverter) Activator.CreateInstance(converterType,convConstructorArgs);
}
public override bool CanConvert(Type objectType)
{
return wrappedConverter.CanConvert(objectType);
}
protected override void WriteJsonInner(JsonWriter writer,JsonSerializer serializer)
{
wrappedConverter.WriteJson(writer,serializer);
}
protected override object ReadJsonInner(JsonReader reader,JsonSerializer serializer)
{
return wrappedConverter.ReadJson(reader,serializer);
}
}
然后可以用来完成上述目标
public class A {
[JsonConverter(typeof(CascadeJsonConverter),// cascading converter
typeof(OptionJsonConverter),new object[0],// converter definition for the top-level type of the property
new object[] { // collection of converter definitions to use while deserializing the contents of the property
new object[] { typeof(DateFormatConverter),"yyyy'-'MM'-'dd'T'mm':'HH':'FF.ssK" }
})]
public Option<DateTime> Time { get; set; }
}
这样,您不仅可以为通用字段使用不同的控制器,而且还可以在类需要为属性类的某些子属性更改转换器的情况下使用。整洁:)
对此的一个警告是,顶级转换器必须使用serializer
和ReadJson
方法中的WriteJson
参数来读取和写入内部值,而不是使用{{1} }和JToken.Load(reader).ToObject<T>()
。否则,将使用未配置的序列化器读取和写入内部值。
如果有更好的方法来完成相同的任务,我真的很感谢您分享它!
本文链接:https://www.f2er.com/3136073.html