namespace CommonConsole { using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; public class ConfigurationJson : Dictionary { public Section this[byte id] => this.Values.FirstOrDefault(x => x.Id == id) ?? new Section(); public new Section this[string key] { get { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentException("Section name should not be null or white space!"); } if (!this.TryGetValue(key, out var section)) { section = new Section(); this[key] = section; } return section; } set { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentException("Section name should not be null or white space!"); } this[key] = value; } } [OnDeserialized] internal void OnDeserialized(StreamingContext _) { foreach (var kvp in this) { kvp.Value.Name = kvp.Key; } } } public class Section { public byte Id { get; set; } [JsonIgnore] public string Name { get; internal set; } public Version Version { get; set; } public Registers Registers { get; set; } public Status Status { get; set; } public Register this[string key] { get { if (this.Registers is null) { return new Register(); } return this.Registers[key]; } set { if (this.Registers != null) { this.Registers[key] = value; } } } public Register this[byte id] => this.Registers?[id] ?? new Register(); } public class Version { public int? First { get; set; } public int? Last { get; set; } public bool InVersion(int version) { if (this.First is null && this.Last is null) { return false; } return (this.First ?? int.MinValue) <= version && (this.First ?? int.MaxValue) >= version; } } public class Registers : Dictionary { public Register this[byte id] => this.Values.FirstOrDefault(x => x.Id == id) ?? new Register(); public new Register this[string key] { get { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentException("Register name should not be null or white space!"); } if (!this.TryGetValue(key, out var register)) { register = new Register(); this[key] = register; } return register; } set { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentException("Register name should not be null or white space!"); } this[key] = value; } } [OnDeserialized] internal void OnDeserialized(StreamingContext _) { foreach (var kvp in this) { kvp.Value.Name = kvp.Key; } } } public class Register { public byte Id { get; set; } [JsonIgnore] public string Name { get; internal set; } public Details Details { get; set; } public Detail this[int version] => this.Details?[version] ?? new Detail(); } public class Details : List { public new Detail this[int version] => this.FirstOrDefault(x => x.Version?.InVersion(version) ?? false) ?? new Detail(); } public class Detail { public string Type { get; set; } public string StaticType { get; set; } public Privilege Privilege { get; set; } public Version Version { get; set; } public Values Values { get; set; } [JsonIgnore] public Value Value { get; set; } [JsonIgnore] public Unit Unit { get; set; } public object this[string property] { get { if (property == nameof(Value)) { return this.Value?.Current; } else if (property == nameof(Unit)) { return this.Unit?.Base; } return null; } set { if (property == nameof(Value) && this.Value != null) { this.Value.Current = value; } else if (property == nameof(Unit) && this.Unit != null) { this.Unit.Base = value; } } } [OnDeserialized] internal void OnDeserialized(StreamingContext _) { try { var valueType = System.Type.GetType( typeName: $"CommonConsole.{this.Type}", throwOnError: false, ignoreCase: true); var instance = Activator.CreateInstance(valueType); if (instance is Value value) { if (this.Values != null) { value.Current = this.Values.Default; } this.Value = value; } } catch (Exception e) { // TODO: Handle exceptions. } } } public class Values { public object Default { get; set; } public object Minimum { get; set; } public object Maximum { get; set; } } public class Privilege { public Access Lvl1 { get; set; } public Access Lvl2 { get; set; } public Access Lvl3 { get; set; } public Access Lvl4 { get; set; } public Access Lvl5 { get; set; } public Access Lvl6 { get; set; } public Access Lvl7 { get; set; } public Access Lvl8 { get; set; } } public enum Access : byte { NS, NA, RO, WO, RW } public class Status : Dictionary { } public class StatusInfo { public byte Id { get; set; } public string Action { get; set; } public string Description { get; set; } } public class AccessConverter : JsonConverter { public override bool CanConvert(Type type) => type == typeof(Access) || type == typeof(Access?); public override object ReadJson(JsonReader reader, Type _, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } var value = serializer.Deserialize(reader); if (Enum.TryParse(value, true, out Access access)) { return access; } return default(Access); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer _1) { if (value != null) { writer.WriteValue($"{value}"); } } } }