public NodePortInfo CreateLooseDynamicPortInfo(NodePort port, out InspectorPropertyInfo info, out InspectorPropertyInfo portInfo, params Attribute[] attributes)
        {
            info = InspectorPropertyInfo.CreateValue(
                port.fieldName,
                1,
                Property.ValueEntry.SerializationBackend,
                new GetterSetter <TValue, int>(
                    ( ref TValue owner ) => 0,
                    (ref TValue owner, int value) => { }
                    ),
                attributes
                );

            portInfo = InspectorPropertyInfo.CreateValue(
                $"{info.PropertyName}:port",
                0,
                Property.ValueEntry.SerializationBackend,
                new GetterSetter <TValue, NodePort>(
                    ( ref TValue owner ) => port,
                    (ref TValue owner, NodePort value) => { }
                    )
                , new HideInInspector()
                );

            // Create a fake property and a fake node
            NodePortInfo nodePortInfo = new NodePortInfo(
                portInfo,
                info,
                port.fieldName,
                port.ValueType,
                Property.Tree.WeakTargets.FirstOrDefault() as Node,                 // Needed?
                ShowBackingValue.Never,
                port.connectionType,
                port.typeConstraint,
                false,
                true,
                port.IsInput,
                false
                );

            return(nodePortInfo);
        }
        protected InspectorPropertyInfo[] GetPropertyInfos()
        {
            if (this.processors == null)
            {
                this.processors = OdinPropertyProcessorLocator.GetMemberProcessors(this.Property);
            }

            var includeSpeciallySerializedMembers = this.Property.ValueEntry.SerializationBackend != SerializationBackend.Unity;
            var infos = InspectorPropertyInfoUtility.CreateMemberProperties(this.Property, typeof(TValue), includeSpeciallySerializedMembers);

            // If we resolve the ports from the port dictionary i might be able to communicate between properties
            // in order to make dynamic port adding cleaner

            // Resolve my own members so I can see them
#if DEBUG_RESOLVER
            infos.AddValue(
                $"resolver:{nameof(infos)}",
                () => this.infos,
                value => { }
                );

            infos.AddValue(
                $"resolver:{nameof( namesToIndex )}",
                () => this.namesToIndex,
                value => { }
                );

            infos.AddValue(
                $"resolver:{nameof( nameToNodePropertyInfo )}",
                () => this.nameToNodePropertyInfo,
                value => { }
                );

            infos.AddValue(
                $"resolver:{nameof( propertyToNodeProperty )}",
                () => this.propertyToNodeProperty,
                value => { }
                );
#endif

            LabelWidthAttribute labelWidthAttribute = Property.GetAttribute <LabelWidthAttribute>();
            displayDynamicPortsAttribute = Property.GetAttribute <DisplayDynamicPortsAttribute>();

            // Port makers
            {
                for (int i = 0; i < infos.Count; ++i)
                {
                    var info = infos[i];
                    if (labelWidthAttribute != null)
                    {
                        if (info.GetAttribute <LabelWidthAttribute>() == null)
                        {
                            info.GetEditableAttributesList().Add(labelWidthAttribute);
                        }
                    }

                    var inputAttribute  = info.GetMemberInfo().GetAttribute <InputAttribute>();
                    var outputAttribute = info.GetMemberInfo().GetAttribute <OutputAttribute>();
                    if (inputAttribute != null || outputAttribute != null)                       // Make a port.... we'll deal with dynamic later
                    {
                        string           baseFieldName     = info.PropertyName;
                        NodePort         port              = Node.GetPort(info.PropertyName);
                        ShowBackingValue showBackingValue  = ShowBackingValue.Always;
                        ConnectionType   connectionType    = ConnectionType.Multiple;
                        TypeConstraint   typeConstraint    = TypeConstraint.None;
                        bool             isDynamicPortList = false;
                        bool             isInput           = false;

                        if (inputAttribute != null)
                        {
                            showBackingValue  = inputAttribute.backingValue;
                            connectionType    = inputAttribute.connectionType;
                            typeConstraint    = inputAttribute.typeConstraint;
                            isDynamicPortList = inputAttribute.dynamicPortList;
                            isInput           = true;
                        }
                        else if (outputAttribute != null)
                        {
                            showBackingValue  = outputAttribute.backingValue;
                            connectionType    = outputAttribute.connectionType;
                            typeConstraint    = outputAttribute.typeConstraint;
                            isDynamicPortList = outputAttribute.dynamicPortList;
                            isInput           = false;
                        }

                        // The port didn't exist... let's just make it exist again?
                        if (port == null)
                        {
                            Node.UpdatePorts();
                            port = Node.GetPort(info.PropertyName);
                        }

                        var portInfo = InspectorPropertyInfo.CreateValue(
                            $"{info.PropertyName}:port",
                            0,
                            Property.ValueEntry.SerializationBackend,
                            new GetterSetter <TValue, NodePort>(
                                ( ref TValue owner ) => port,
                                (ref TValue owner, NodePort value) => { }
                                )
                            , new HideInInspector()
                            );

                        var nodePortInfo = new NodePortInfo(
                            portInfo,
                            info,
                            baseFieldName,
                            info.TypeOfValue,
                            Property.Tree.WeakTargets.FirstOrDefault() as Node,                             // Needed?
                            showBackingValue,
                            connectionType,
                            typeConstraint,
                            isDynamicPortList,
                            false,
                            isInput,
                            true
                            );

                        propertyToNodeProperty[info.PropertyName]     = portInfo.PropertyName;
                        nameToNodePropertyInfo[portInfo.PropertyName] = nodePortInfo;

                        if (isDynamicPortList)
                        {
                            var listDrawerAttributes = info.GetAttribute <ListDrawerSettingsAttribute>();
                            if (listDrawerAttributes == null)
                            {
                                listDrawerAttributes = new ListDrawerSettingsAttribute();
                                info.GetEditableAttributesList().Add(listDrawerAttributes);
                            }

                            listDrawerAttributes.Expanded   = true;
                            listDrawerAttributes.ShowPaging = false;
                        }

                        infos.Insert(i, portInfo);
                        ++i;                         // Skip the next entry
                    }
                }

                if (displayDynamicPortsAttribute != null)
                {
                    // If I find any dynamic ports that were not covered here then add them as well
                    // This should include anything that wouldn't be directly related to the ports I *did* find
                    foreach (var port in Node.Ports)
                    {
                        if (port.IsDynamic)
                        {
                            // If is likely to be an automatically added port?
                            if (IsManagedPort(port.fieldName))
                            {
                                continue;
                            }

                            // No one claimed it?
                            var nodePortInfo = CreateLooseDynamicPortInfo(port, out var info, out var portInfo, displayDynamicPortsAttribute);

                            propertyToNodeProperty[info.PropertyName]     = portInfo.PropertyName;
                            nameToNodePropertyInfo[portInfo.PropertyName] = nodePortInfo;

                            infos.Add(info);
                            infos.Add(portInfo);
                        }
                    }
                }
            }

            for (int i = 0; i < this.processors.Count; i++)
            {
                ProcessedMemberPropertyResolverExtensions.ProcessingOwnerType = typeof(TValue);
                this.processors[i].ProcessMemberProperties(infos);
            }

            EditorApplication.update -= Update;
            if (displayDynamicPortsAttribute != null)
            {
                EditorApplication.update += Update;
            }

            knownPortKeys.Clear();
            knownPortKeys.AddRange(Node.Ports.Select(x => x.fieldName));
            return(InspectorPropertyInfoUtility.BuildPropertyGroupsAndFinalize(this.Property, typeof(TValue), infos, includeSpeciallySerializedMembers));
        }