using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Tango.Core; using Tango.Core.Commands; namespace Tango.FSE.Procedures { public class DebugNode : ExtendedObject { private Object _originalValue; public String Name { get; set; } public Object ParentObject { get; set; } private Object _value; public Object Value { get { return _value; } set { _value = value; if (_originalValue == null) { _originalValue = _value; } DisplayValue = GetDisplayValue(_value); RaisePropertyChangedAuto(); } } public bool IsSimpleValue { get; set; } public String Type { get; set; } public PropertyInfo PropertyInfo { get; set; } public FieldInfo FieldInfo { get; set; } public Type MemberType { get { if (PropertyInfo != null) { return PropertyInfo.PropertyType; } else if (FieldInfo != null) { return FieldInfo.FieldType; } else { return Value.GetType(); } } } private bool _isEdited; public bool IsEdited { get { return _isEdited; } set { _isEdited = value; RaisePropertyChangedAuto(); } } public RelayCommand UpdateValueCommand { get; set; } public bool IsEditable { get { if (IsSimpleValue) { return false; //Sorry can't update simple script symbols as they are passed to me by value... } if (MemberType != null && MemberType.IsValueTypeOrString() && ((PropertyInfo != null && PropertyInfo.SetMethod != null) || FieldInfo != null)) { return true; } return false; } } private Object _displayValue; public Object DisplayValue { get { return _displayValue; } set { _displayValue = value; RaisePropertyChangedAuto(); } } public List Nodes { get { return GetChildNodes(); } } public DebugNode() { UpdateValueCommand = new RelayCommand(UpdateValue); } private void UpdateValue() { try { if (IsSimpleValue && Value != null) { _value = Convert.ChangeType(DisplayValue, Value.GetType()); IsEdited = _originalValue.ToStringSafe() != Value.ToStringSafe(); } else if (IsEditable && ((PropertyInfo != null && PropertyInfo.SetMethod != null) || FieldInfo != null)) { if (PropertyInfo != null) { _value = Convert.ChangeType(DisplayValue, PropertyInfo.PropertyType); PropertyInfo.SetValue(ParentObject, Value); IsEdited = _originalValue.ToStringSafe() != Value.ToStringSafe(); } else if (FieldInfo != null) { _value = Convert.ChangeType(DisplayValue, FieldInfo.FieldType); FieldInfo.SetValue(ParentObject, Value); IsEdited = _originalValue.ToStringSafe() != Value.ToStringSafe(); } } } catch { } DisplayValue = GetDisplayValue(Value); } private List GetChildNodes() { List childNodes = new List(); if (Value == null) return childNodes; var type = Value.GetType(); if (type.IsValueTypeOrString()) { return childNodes; } if (typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(String)) { List list = (Value as IEnumerable).Cast().ToList(); for (int i = 0; i < list.Count; i++) { var item = list[i]; DebugNode listNode = new DebugNode(); listNode.Name = $"[{i}]"; listNode.Value = item; listNode.Type = GetFriendlyName(item.GetType()); childNodes.Add(listNode); } } else { foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { DebugNode propNode = new DebugNode(); propNode.Type = GetFriendlyName(prop.PropertyType); propNode.Name = prop.Name; propNode.Value = prop.GetValue(Value); propNode.PropertyInfo = prop; propNode.ParentObject = Value; childNodes.Add(propNode); } foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public)) { DebugNode propNode = new DebugNode(); propNode.Type = GetFriendlyName(field.FieldType); propNode.Name = field.Name; propNode.Value = field.GetValue(Value); propNode.FieldInfo = field; propNode.ParentObject = Value; childNodes.Add(propNode); } } return childNodes; } public static DebugNode CreateNode(String name, Object obj) { DebugNode node = new DebugNode(); node.Name = name; node.Value = obj; node.Type = GetFriendlyName(obj.GetType()); if (obj.GetType().IsValueTypeOrString()) { node.IsSimpleValue = true; } return node; } private static String GetFriendlyName(Type type) { if (type == typeof(int)) return "int"; else if (type == typeof(short)) return "short"; else if (type == typeof(byte)) return "byte"; else if (type == typeof(bool)) return "bool"; else if (type == typeof(long)) return "long"; else if (type == typeof(float)) return "float"; else if (type == typeof(double)) return "double"; else if (type == typeof(decimal)) return "decimal"; else if (type == typeof(string)) return "string"; else if (type.IsGenericType) return type.Name.Split('`')[0] + "<" + string.Join(", ", type.GetGenericArguments().Select(x => GetFriendlyName(x)).ToArray()) + ">"; else return type.Name; } private static Object GetDisplayValue(Object value) { if (value == null) { return "null"; } else if (value.GetType().IsValueTypeOrString()) { return value; } else if (typeof(IEnumerable).IsAssignableFrom(value.GetType())) { List list = (value as IEnumerable).Cast().ToList(); return $"Count = {list.Count}"; } return value.ToStringSafe(); } } }