using System.Collections; using System.Text; namespace qmonlib.Dependencies.Object.Dynamic { public class DyoMember { #region *** Constants *** public const string PathSeparator = "/"; public const string PathRoot = "."; #endregion #region *** Properties *** private long Id { get; } public ElementType Type { get; } private Dyo? Root { get; } private DyoMember? Parent { get; } public string Name { get; } public object? Value { get; private set; } public DyoMember[] Members => _members.ToArray(); #endregion #region *** Fields *** private static long _idCnt; private IList _members = new List(); #endregion #region *** Indexer *** public DyoMember this[string name] => Get(name); public DyoMember this[int ordinal] => _members.Skip(ordinal).First(); #endregion #region *** Constructors *** public DyoMember(Dyo? root, ElementType type, DyoMember? parent, string name, object? value = null) { Id = root?.GetNextId() ?? -1; Type = type; Parent = parent; Root = root; Name = name; Value = value; } #endregion #region *** Operations *** public DyoMember Add(string name, ElementType elementType, object? value = null) { ThrowIfExists(name); var item = new DyoMember(Root ?? (Dyo)this, elementType, this, name, value); _members.Add(item); return item; } public void Remove(string name) { var item = Get(name); item.Clear(); _members.Remove(item); } public void Clear() { foreach (var member in _members) member.Clear(); _members.Clear(); } public DyoMember Get(string name) { ThrowIfNotExists(name); var item = _members.First(x => x.Name == name); return item; } public void Set(string name, object? value) { var item = Get(name); item.Value = value; } public void Reset() { foreach (var member in _members) member.Reset(); Value = null; } public bool Exists(string name, Dyo.ElementType? elementType = null) { if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); var exists = elementType!=null ? _members.Any(x => x.Name == name && x.Type == elementType) : _members.Any(x => x.Name == name); return exists; } public string GetPath() { if (Parent == null) return Dyo.PathRoot; var path = Parent.GetPath() + Dyo.PathSeparator + Name; return path; } public string Dump() { var sb = new StringBuilder(); sb.Append(Name).Append(" [#").Append(Id).Append(";").Append(Type).Append("] ").Append(_members.Count).Append(" members").AppendLine(); sb.Append("\t").Append("Path:").Append(GetPath()).AppendLine(); if (Type == ElementType.Value) sb.Append("\t").Append("Value:").Append(Value == null ? "NULL" : Value.ToString()).AppendLine(); foreach (var member in _members) sb.Append("\t* ").Append(member.Dump()); return sb.ToString(); } #endregion #region *** Private Operations *** private void ThrowIfNotExists(string name) { if (!Exists(name)) throw new Exception($"Dyo member with name '{name}' does not exist."); } private void ThrowIfExists(string name) { if (Exists(name)) throw new Exception($"Dyo member with name '{name}' already exists."); } private long GetNextId() { _idCnt++; return _idCnt; } #endregion #region *** Nested Types *** public enum ElementType { Value, Object, Collection, Root } #endregion } }