private static void FillNodes(List <InputParameterNode> res, InputParameterNode node)
 {
     res.Add(node);
     foreach (var item in node.Children)
     {
         FillNodes(res, item);
     }
 }
        private static void GetNodesCore(InputParameterNode parent, bool isOutput)
        {
            if (parent.OwnerType.GetCustomAttribute <ParameterObjectAttribute>() == null ||
                !parent.OwnerType.GetCustomAttribute <ParameterObjectAttribute>().IsInput)
            {
                return;
            }
            if (parent.Property != null)
            {
                if (parent.Property.PropertyType.IsValueType)
                {
                    return;
                }
            }

            PropertyInfo[]      props    = parent.Owner.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            List <PropertyInfo> filtered = props.ToList();

            if (!isOutput)
            {
                filtered = filtered.Where(p => p.GetCustomAttribute <InputParameterAttribute>() != null && p.GetCustomAttribute <InputParameterAttribute>().IsInput).ToList();
            }
            else
            {
                filtered = filtered.Where(p => p.GetCustomAttribute <OutputParameterAttribute>() != null && p.GetCustomAttribute <OutputParameterAttribute>().IsOutput).ToList();
            }
            foreach (PropertyInfo pInfo in filtered)
            {
                InputParameterAttribute attr  = pInfo.GetCustomAttribute <InputParameterAttribute>();
                InputParameterNode      child = new InputParameterNode();
                child.Name      = pInfo.Name;
                child.Parent    = parent;
                child.Owner     = pInfo.GetValue(parent.Owner);
                child.OwnerType = pInfo.DeclaringType;
                child.Property  = pInfo;
                if (attr != null)
                {
                    child.MinValue = attr.MinValue;
                    child.MaxValue = attr.MaxValue;
                    child.Change   = attr.Change;
                }

                if (pInfo.PropertyType.IsClass)
                {
                    GetNodesCore(child, isOutput);
                    if (child.Children.Count > 0)
                    {
                        parent.Children.Add(child);
                    }
                }
                else if (pInfo.PropertyType.IsValueType)
                {
                    parent.Children.Add(child);
                }
            }
        }
        public static List <InputParameterNode> GetOutputNodes(object owner)
        {
            List <InputParameterNode> res  = new List <InputParameterNode>();
            InputParameterNode        node = new InputParameterNode()
            {
                Owner = owner, Name = owner.GetType().Name, OwnerType = owner.GetType()
            };

            GetNodesCore(node, true);
            FillNodes(res, node);
            return(res);
        }