Я решил это, используя поле abstract
в качестве discriminator
в атрибуте. Это поле будет определено в root
и будет переопределено только в leaf
-s.Затем отдельно я бы реализовал различающееся объединение.
Чтобы иметь возможность разыгрывать на любом уровне в иерархии, я бы украсил промежуточные абстрактные классы их соответствующими листами:
Так, например, имея классиерархия, подобная этой:
M
M1:M
, M2:M
[M11:M1
, M12:M1
];[M21:M2
, M22:M2
]
где листы M11,M12,M21,M22
я написал следующий код:
Root
[JsonConverter(typeof(JsonSubTypes.JsonSubtypes), propType)]
[JsonSubTypes.JsonSubtypes.KnownSubType(typeof(M.M1.M11),Leaf.M11)]
[JsonSubTypes.JsonSubtypes.KnownSubType(typeof(M.M1.M12), Leaf.M12)]
[JsonSubTypes.JsonSubtypes.KnownSubType(typeof(M.M2.M21), Leaf.M21)]
[JsonSubTypes.JsonSubtypes.KnownSubType(typeof(M.M2.M22), Leaf.M22)]
public abstract partial class M
{
public static void Process(M message){
switch(message.MKind){
case M.Discriminator.M1 : M.M1.Process(message.AsM1);break;
case M.Discriminator.M2: M.M2.Process(message.AsM2);break;
}
}
[JsonIgnore]
public bool IsM1=>this.MKind==Discriminator.M1;
[JsonIgnore]
public bool IsM2=>this.MKind==Discriminator.M2;
[JsonIgnore]
public M1 AsM1=>this as M1;
[JsonIgnore]
public M2 AsM2=>this as M2;
private const string propType="$LeafKind";
public enum Discriminator {
M1=0,
M2=1
}
public enum Leaf {
M11=M1.Discriminator.M11*10,
M12=M1.Discriminator.M12*10,
M21=M2.Discriminator.M21*10,
M22=M2.Discriminator.M22*10
}
[JsonProperty(propType)]
public abstract Leaf LeafKind{get;}
protected abstract Discriminator MKind{get;}
public Discriminator Kind=>this.MKind;
public DateTime timestamp { get;}
}
Абстрактная ветвь (уровень 2)
[JsonSubTypes.JsonSubtypes.KnownSubType(typeof(M.M1.M11),
M.Leaf.M11)]
[JsonSubTypes.JsonSubtypes.KnownSubType(typeof(M.M1.M12),M.Leaf.M12)]
public abstract partial class M1:M
{
public static void Process(M1 message){
switch(message.M1Kind){
case M1.Discriminator.M11 : M1.M11.Process(message.AsM11);break;
case M1.Discriminator.M12: M1.M12.Process(message.AsM12);break;
}
}
protected override M.Discriminator MKind => M.Discriminator.M1;
public new enum Discriminator {
M11=10,
M12=11
}
public new Discriminator Kind => this.M1Kind;
protected abstract Discriminator M1Kind { get; }
[JsonIgnore]
public bool IsM11=>this.M1Kind==M1.Discriminator.M11;
[JsonIgnore]
public bool IsM12=>this.M1Kind==M1.Discriminator.M12;
[JsonIgnore]
public M11 AsM11=>this as M11;
[JsonIgnore]
public M12 AsM12=>this as M12;
}
Лист
public class M11 : M1
{
public static void Process(M11 message){
Console.WriteLine(message.Value);
}
public bool Value{get;set;}
protected override Discriminator M1Kind => Discriminator.M11;
public override Leaf LeafKind => Leaf.M11;
}
Для возможности приведения объекта типа M11
в M1
Мне нужно украсить M1
с помощью KnownSubTypes
, но переопределить discriminator
только в листьях.
PS Я не добавил сюда все subtypes
, кроме васполную реализацию с небольшим образцом можно найти в исходном коде
обновлении Я переопределил иерархию, используя enum
вместо строки как Discriminator
.