// Tries to get a pretty name from property passed in, or null if none found
        public static string PrettyName(this object val)
        {
            string name = null;

            if (val is P.ValueProperty)
            {
                P.ValueProperty val_prop = val as P.ValueProperty;
                if (val_prop.Name != null)
                {
                    name = val_prop.Name.ToString();
                }
            }
            if (string.IsNullOrEmpty(name) && val is P.Property)
            {
                P.Property prop = val as P.Property;
                name = prop.GetPathName();
                if (!string.IsNullOrEmpty(name))
                {
                    name = name.LastName();
                }
                else if (prop.Parent != null)
                {
                    name = prop.Parent.GetChilds().FindName(prop);
                    //TODO: Could add further checking by traversing parent properties
                    //      and checking Properties- resp. PropertyList-related childs
                    //if (string.IsNullOrEmpty(name)) ...
                }
            }
            return(name);
        }
 // Get all named value properties
 public static List <string> Names(this P.Properties props)
 {
     return(props
            .Where(prop => (prop is P.ValueProperty) && !str.IsNullOrEmpty((prop as P.ValueProperty).Name))
            .Select(prop => {
         P.ValueProperty val = prop as P.ValueProperty;
         string s = val.Name.ToString();
         if (val.Index != 0)
         {
             s += "#" + val.Index;
         }
         return s;
     })
            .ToList()
            );
 }
        // Find name of value instance passed, or null if not found
        public static string FindName(this P.Properties props, object value)
        {
            string name = null;

            foreach (P.Property prop in props)
            {
                if (prop is P.ValueProperty && prop == value)
                {
                    P.ValueProperty v = (prop as P.ValueProperty);
                    if (!str.IsNullOrEmpty(v.Name))
                    {
                        name = v.Name.ToString();
                    }
                    break;
                }
            }
            return(null);
        }
        // Find a value property by name
        public static P.Property Named(this P.Properties props, string name, int index = -1)
        {
            if (index < 0)
            {
                int pos = name.IndexOf('#');
                if (pos > 0)
                {
                    string idx = name.Substring(pos + 1);
                    name = name.Substring(0, pos);
                    if (!int.TryParse(idx, out index))
                    {
                        return(null);
                    }
                }
            }
            if (index >= 0)
            {
                return(props.FirstOrDefault(prop => {
                    if (prop is P.ValueProperty)
                    {
                        P.ValueProperty val = prop as P.ValueProperty;
                        str prop_name = val.Name;
                        if (!str.IsNullOrEmpty(prop_name))
                        {
                            return (val.Index == index) && (prop_name.ToString() == name);
                        }
                    }
                    return false;
                }));
            }

            return(props.FirstOrDefault(prop => {
                if (prop is P.ValueProperty)
                {
                    str prop_name = (prop as P.ValueProperty).Name;
                    if (!str.IsNullOrEmpty(prop_name))
                    {
                        return prop_name.ToString() == name;
                    }
                }
                return false;
            }));
        }
        internal D.DifferenceNode _Compare(P.Property left, P.Property right)
        {
            D.DifferenceNode node = new D.DifferenceNode(left.ToString(), left, right);
            D.DifferenceNode sub;

            if ((left == null || right == null) && (left != right))
            {
                return(node);
            }

            // Do some by-name blacklisting to skips things like delta timestamps
            if (left is P.ValueProperty)
            {
                P.ValueProperty val_prop = left as P.ValueProperty;
                if (val_prop.Name != null)
                {
                    string name = val_prop.Name.ToString();
                    if (_blacklisted.Contains(name))
                    {
                        return(null);
                    }
                }
            }

            Dictionary <string, object> left_childs  = new Dictionary <string, object>(left.GetChilds());
            Dictionary <string, object> right_childs = new Dictionary <string, object>(right.GetChilds());

            while (left_childs.Count > 0)
            {
                var pair = left_childs.First();

                object left_sub = pair.Value;
                left_childs.Remove(pair.Key);

                object right_sub = null;
                if (right_childs.ContainsKey(pair.Key))
                {
                    right_sub = right_childs[pair.Key];
                    right_childs.Remove(pair.Key);
                }

                if (_blacklisted.Contains(pair.Key))
                {
                    continue;
                }

                if (right_sub == null && left_sub != null)
                {
                    sub = new D.DifferenceNode(null, left_sub, null);
                }
                else if (left_sub is P.Property)
                {
                    sub = _Compare(left_sub as P.Property, right_sub as P.Property);
                }
                else
                {
                    sub = _CompareObject(left_sub, right_sub);
                }
                if (sub != null)
                {
                    sub.Title = pair.Key;
                    node.Add(sub);
                }
            }

            foreach (var pair in right_childs)
            {
                if (!_blacklisted.Contains(pair.Key))
                {
                    node.Add(pair.Key, null, pair.Value);
                }
            }

            return((node.ChildCount > 0) ? node : null);
        }