Exemplo n.º 1
0
        public static void ScanTypeForProperties <TOptions>(out TypeArgumentInfo tInfo)
        {
            tInfo = new TypeArgumentInfo();
            PropertyInfo[] propertiesOnType = typeof(TOptions).GetTypeInfo().GetProperties(BindingFlags.Instance | BindingFlags.Public);

            // first of all, find the commandArgument, if any.
            tInfo.ActionArgument = FindCommandProperty(propertiesOnType);

            // we want to be able to support empty groups.
            if (tInfo.ActionArgument != null && IsEnum(tInfo.ActionArgument.PropertyType))
            {
                // get the values of the enum.
                var enumValues = Enum.GetValues(tInfo.ActionArgument.PropertyType);

                // Sort the enum by the enum values
                Array.Sort(enumValues);

                // add them to the dictionary now to make sure we preserve the order
                foreach (var val in enumValues)
                {
                    if (!tInfo.ArgumentGroups.ContainsKey(val.ToString()))
                    {
                        tInfo.ArgumentGroups.Add(val.ToString(), new ArgumentGroupInfo());
                    }
                }
            }

            // parse the rest of the properties
            foreach (var property in propertiesOnType)
            {
                // get the group containing this property (note: more than one group can have the same property)
                // this allows common required parameters

                var groupsWhereThePropertyIsParticipating = GetGroupsForProperty(tInfo, property);

                var actualAttribs = property.GetCustomAttributes <ActualArgumentAttribute>().ToList();
                if (actualAttribs.Count > 1)
                {
                    throw new ArgumentException($"Only one of Required/Optional attribute are allowed per property ({property.Name}). [Red!Help information might be incorrect!]");
                }

                // if we have no attributes on that property, move on
                ActualArgumentAttribute baseAttrib = actualAttribs.FirstOrDefault();
                if (baseAttrib == null)
                {
                    continue;
                }

                // add the property to add the groups it is a part of
                if (baseAttrib is RequiredArgumentAttribute)
                {
                    foreach (ArgumentGroupInfo grpPropInfo in groupsWhereThePropertyIsParticipating)
                    {
                        // do we have an override for this property? If we do, use that, otherwise use the regular one.
                        if (!grpPropInfo.OverridePositions.TryGetValue(property, out int requiredPositionIndex))
                        {
                            requiredPositionIndex = (int)baseAttrib.GetArgumentId();
                        }

                        if (grpPropInfo.RequiredArguments.ContainsKey(requiredPositionIndex))
                        {
                            throw new ArgumentException("Two required arguments share the same position!!");
                        }

                        grpPropInfo.RequiredArguments[requiredPositionIndex] = property;
                    }
                }
                else if (baseAttrib is OptionalArgumentAttribute)
                {
                    foreach (ArgumentGroupInfo grpPropInfo in groupsWhereThePropertyIsParticipating)
                    {
                        if (grpPropInfo.OptionalArguments.ContainsKey((string)baseAttrib.GetArgumentId()))
                        {
                            throw new ArgumentException("Two optional arguments share the same name!!");
                        }

                        grpPropInfo.OptionalArguments[(string)baseAttrib.GetArgumentId()] = property;
                    }
                }
            }

            ArgumentGroupInfo grp;

            // remove the empty one, if empty
            if (tInfo.ArgumentGroups.TryGetValue(string.Empty, out grp))
            {
                if (grp.OptionalArguments.Count == 0 && grp.RequiredArguments.Count == 0)
                {
                    tInfo.ArgumentGroups.Remove(string.Empty);
                }
            }
        }