I wrote a test programe with .NET 6
static void Main(string[] args) {
JsonSerializerOptions options = new JsonSerializerOptions() {
Converters = {
new JsonStringEnumConverter(),
new JsonStringAbilityEffectFactoryConverter()
}
};
AbilityTemplate dictionary = JsonSerializer.Deserialize<AbilityTemplate>(@"
{
""Id"": ""StandardShot"",
""Price"": 10,
""Size"": 1,
""Rarity"": ""Common"",
""AbilityEffectFactory"": {
""Id"":""StandardShotEffectFactory""
},
""PropertyBasicValues"": {
""CoolDownRate"": 5,
""CastRate"": ""Infinity""
}
}
");
}
}
internal class JsonStringAbilityEffectFactoryConverter : JsonConverter<AbilityEffectFactory> {
public override AbilityEffectFactory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
string id = "";//Break point here. This method is just casually implemented because I am merely especting this method to be called.
while (reader.Read()) {
id = reader.GetString();
}
return AbilityEffectFactory.Dictionary[id];
}
public override void Write(Utf8JsonWriter writer, AbilityEffectFactory value, JsonSerializerOptions options) {
throw new NotImplementedException();
}
}
And my AbilityTemplate Class is like this:
public class AbilityTemplate : RarityObject {
public AbilityTemplate(string id, int price, int size, Rarity rarity, AbilityEffectFactory abilityEffectFactory, in Ability.PropertyCollection propertyBasicValues) {
Id = id;
Price = price;
Size = size;
Rarity = rarity;
AbilityEffectFactory = abilityEffectFactory;
PropertyBasicValues = propertyBasicValues;
}
internal static readonly Dictionary<string, AbilityTemplate> dictionary = new Dictionary<string, AbilityTemplate>();
public static IReadOnlyDictionary<string, AbilityTemplate> Dictionary => dictionary;
public string Id { get; }
public int Price { get; }
public override Rarity Rarity { get; }
public int Size { get; }
public AbilityEffectFactory AbilityEffectFactory { get; }
public Ability.PropertyCollection PropertyBasicValues { get; }
}
The parent class RarityObject is just a simple abstract class with one field which is overrided:
public abstract class RarityObject {
public abstract Rarity Rarity { get; }
}
However, when the code executes, I was thrown exception:
System.InvalidOperationException: 'Each parameter in the deserialization constructor on type 'Enigma.Game.AbilityTemplate' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. The match can be case-insensitive.'
I cannot understand how can this exception occur. Each field written in Json text is already exactly matched to properties of my AbilityTemplate class.
Update0 My AbilityEffectFactory is an abstract class, maybe thats what went wrong.
Update1 I modified the Converter to be like this:
internal class JsonStringAbilityTemplateConverter : JsonConverter<AbilityTemplate> {
public override AbilityTemplate Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
string id = "";//Break point
while (reader.Read()) {
id = reader.GetString();
}
return new AbilityTemplate();
}
public override void Write(Utf8JsonWriter writer, AbilityTemplate value, JsonSerializerOptions options) {
throw new NotImplementedException();
}
}
But I still got exception:
System.NotSupportedException: 'Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'Enigma.Game.AbilityEffectFactory'. Path: $.AbilityEffectFactory | LineNumber: 6 | BytePositionInLine: 45.'
And the break point wasn't hit.How can this be posible as the system already read to line 6?