做一些配置文件时常用到的功能,话不多説,直接上代码
使用的库是Newtonsoft,这个很常见了,安装之类的,这里就不赘述了
核心代码:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
/// <summary>
/// 用于多态序列化
/// </summary>
public class PolyConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
#pragma warning disable CS8765 // 参数类型的为 Null 性与重写成员不匹配(可能是由于为 Null 性特性)。
#pragma warning disable CS8604 // 引用类型参数可能为 null。
#pragma warning disable CS8603 // 可能返回 null 引用。
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
foreach (var item in jObject.Properties())
{
Type type = Type.GetType(item.Name);
var value = item.Value.ToObject(type);
return value;
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject jObject = new JObject();
jObject.Add(value.GetType().FullName, JToken.FromObject(value));
serializer.Serialize(writer, jObject);
}
#pragma warning restore CS8603 // 可能返回 null 引用。
#pragma warning restore CS8604 // 引用类型参数可能为 null。
#pragma warning restore CS8765 // 参数类型的为 Null 性与重写成员不匹配(可能是由于为 Null 性特性)。
#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
}
/// <summary>
/// 用于多态列表的转化
/// </summary>
/// <typeparam name="T"></typeparam>
public class PolyListConverter<T> : JsonConverter
{
#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
#pragma warning disable CS8765 // 参数类型的为 Null 性与重写成员不匹配(可能是由于为 Null 性特性)。
#pragma warning disable CS8604 // 引用类型参数可能为 null。
#pragma warning disable CS8603 // 可能返回 null 引用。
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
List<T> values = new List<T>();
foreach (var item in jObject.Properties())
{
Type type = Type.GetType(item.Name);
var value = item.Value.ToObject(type);
values.Add((T)value);
}
return values;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var values = (List<T>)value;
JObject jObject = new JObject();
foreach (var item in values)
{
jObject.Add(item?.GetType().FullName, JToken.FromObject(item));
}
var p = jObject.Properties();
//foreach (var item in p)
//{
// Debug.Log(item.Name);
//}
serializer.Serialize(writer, jObject);
}
#pragma warning restore CS8603 // 可能返回 null 引用。
#pragma warning restore CS8604 // 引用类型参数可能为 null。
#pragma warning restore CS8765 // 参数类型的为 Null 性与重写成员不匹配(可能是由于为 Null 性特性)。
#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
}
使用以及对应的情况
public class JsonTest
{
public void Test()
{
List<Monster> monsters = new List<Monster>()
{
new Monster()
{
Name ="怪物1",
AttackMode = new WeaponAttack(),
MoveMode = new GroundMove(),
},
new Monster()
{
Name ="怪物2",
AttackMode = new ClawAttack(),
MoveMode = new AirMove(),
}
};
var json = JsonConvert.SerializeObject(monsters, Formatting.Indented);
Console.WriteLine(json);
var result = JsonConvert.DeserializeObject<List<Monster>>(json);
}
}
public class Monster
{
//首先我们这里有个怪物,但是怪物的攻击和移动方式有很多种,所以对它进行抽象
//当我们需要给这个怪物扩展攻击方式或者移动方式时
//只需要继承基类,而且还可以通过反射的方式,获取所有的实现来进行配置
public string Name { get; set; } = "None";
[JsonConverter(typeof(PolyConverter))]
public Attack? AttackMode { get; set; }
[JsonConverter(typeof(PolyConverter))]
public Move? MoveMode { get; set; }
}
public abstract class Attack
{
public virtual string Weapon { get; set; } = "无";
}
public abstract class Move
{
public abstract string Walk { get; set; }
}
//--------------------------- Attack
public sealed class WeaponAttack: Attack
{
public override string Weapon { get; set; } = "使用武器攻击";
}
public sealed class ClawAttack : Attack
{
public override string Weapon { get; set; } = "使用爪子攻击";
}
//--------------------------- Move
public sealed class GroundMove : Move
{
public override string Walk { get; set; } = "在地面上行走";
}
public sealed class AirMove : Move
{
public override string Walk { get; set; } = "在空中飞行";
}
上述运行之后的结果
1.转换成json后的
2.从json转换成对应实例
很方便吧
通过反射获取基类所有实现的方式,下篇再见