Exemplo n.º 1
0
        /// <summary>
        /// Creates an options entry wrapper for the specified property, iterating its internal
        /// fields to create sub-options if needed (recursively).
        /// </summary>
        /// <param name="info">The property to wrap.</param>
        /// <param name="spec">The option title and tool tip.</param>
        /// <param name="depth">The current depth of iteration to avoid infinite loops.</param>
        /// <returns>An options wrapper, or null if no inner properties are themselves options.</returns>
        internal static CompositeOptionsEntry Create(IOptionSpec spec, PropertyInfo info,
                                                     int depth)
        {
            var type      = info.PropertyType;
            var composite = new CompositeOptionsEntry(info.Name, spec, type);

            // Skip static properties if they exist
            foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.
                                                    Instance))
            {
                var entry = TryCreateEntry(prop, depth + 1);
                if (entry != null)
                {
                    composite.AddField(prop, entry);
                }
            }
            return(composite.ChildCount > 0 ? composite : null);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates an options entry if an attribute is a valid IOptionSpec or
        /// DynamicOptionAttribute.
        /// </summary>
        /// <param name="attribute">The attribute to parse.</param>
        /// <param name="prop">The property to inspect.</param>
        /// <param name="depth">The current depth of iteration to avoid infinite loops.</param>
        /// <returns>The OptionsEntry created from the attribute, or null if none was.</returns>
        private static IOptionsEntry TryCreateEntry(Attribute attribute, PropertyInfo prop,
                                                    int depth)
        {
            IOptionsEntry result = null;

            if (prop == null)
            {
                throw new ArgumentNullException(nameof(prop));
            }
            if (attribute is IOptionSpec spec)
            {
                if (string.IsNullOrEmpty(spec.Title))
                {
                    spec = HandleDefaults(spec, prop);
                }
                // Attempt to find a class that will represent it
                var type = prop.PropertyType;
                result = FindOptionClass(spec, prop);
                // See if it has entries that can themselves be added, ignore
                // value types and avoid infinite recursion
                if (result == null && !type.IsValueType && depth < 16 && type !=
                    prop.DeclaringType)
                {
                    result = CompositeOptionsEntry.Create(spec, prop, depth);
                }
            }
            else if (attribute is DynamicOptionAttribute doa &&
                     typeof(IOptionsEntry).IsAssignableFrom(doa.Handler))
            {
                try {
                    result = Activator.CreateInstance(doa.Handler) as IOptionsEntry;
                } catch (TargetInvocationException e) {
                    PUtil.LogError("Unable to create option handler for property " +
                                   prop.Name + ":");
                    PUtil.LogException(e.GetBaseException() ?? e);
                } catch (MissingMethodException) {
                    PUtil.LogWarning("Unable to create option handler for property " +
                                     prop.Name + ", it must have a public default constructor");
                }
            }
            return(result);
        }