/// <summary> /// Subclasses may override this method to provide custom logic in order to create description string for <see cref="NamedParameterGroup"/> which did not contain matching properties. /// </summary> /// <param name="namedGroup">The <see cref="NamedParameterGroup"/>.</param> /// <returns>Current implementation returns <see cref="NamedParameterGroup.Description"/> of given <paramref name="namedGroup"/>, or empty string, if the <see cref="NamedParameterGroup.Description"/> is <c>null</c>.</returns> protected virtual String CreateFreeFormParameterGroupDescription( NamedParameterGroup namedGroup ) { var desc = namedGroup.Description; return(String.IsNullOrEmpty(desc) ? "" : $" {desc}"); }
/// <summary> /// Subclasses may override this with custom logic on how to construct detailed parameter description string for one whole <see cref="NamedParameterGroup"/>. /// </summary> /// <param name="groupInfo">Group info dictionary created by <see cref="CreateGroupInfo"/></param> /// <param name="namedGroup">The <see cref="NamedParameterGroup"/>.</param> /// <returns>Current implementation calls <see cref="CreatePropertyBasedParametersDescription"/> if the <paramref name="groupInfo"/> contains value for <see cref="NamedParameterGroup.Name"/> of <paramref name="namedGroup"/>; otherwise returns result of <see cref="CreateFreeFormParameterGroupDescription"/>.</returns> protected virtual String CreateGroupParameterString( TGroupInfoDictionary groupInfo, NamedParameterGroup namedGroup ) { return ($@"{namedGroup.Name}: {( groupInfo.TryGetValue( namedGroup.Name, out var props ) ? this.CreatePropertyBasedParametersDescription( namedGroup, props ) : this.CreateFreeFormParameterGroupDescription( namedGroup ) )}"); }
/// <summary> /// Subclasses may override this with custom logic on how to construct detailed parameter description string for all properties related to single <see cref="NamedParameterGroup"/>. /// </summary> /// <param name="namedGroup">The <see cref="NamedParameterGroup"/>.</param> /// <param name="props">Information about required (first element) and optional (second element) parameters.</param> /// <returns>Current implementation sorts the parameters according to <see cref="NamedParameterGroup.RequiredParametersComparer"/> and <see cref="NamedParameterGroup.OptionalParametersComparer"/> comparers of <paramref name="namedGroup"/>, and then constructs one line for each parameter, checking for property type and <see cref="RequiredAttribute"/> and <see cref="DescriptionAttribute"/> possibly applied on property.</returns> protected virtual String CreatePropertyBasedParametersDescription( NamedParameterGroup namedGroup, TGroupInfoValues props ) { var reqCount = props.Item1.Count; var allParameters = props.Item1 .OrderBy(p => p, namedGroup.RequiredParametersComparer) .Concat(props.Item2.OrderBy(p => p, namedGroup.OptionalParametersComparer)) .Select(p => { var desc = p.Item1.GetCustomAttribute <DescriptionAttribute>(); var req = p.Item1.GetCustomAttribute <RequiredAttribute>(); var v = desc?.ValueName; if (String.IsNullOrEmpty(v)) { var propertyType = p.Item1.PropertyType; if (Equals(propertyType, typeof(Boolean)) || Equals(propertyType, typeof(Boolean? ))) { v = "true|false"; } else if (propertyType. #if NETSTANDARD1_0 GetTypeInfo(). #endif IsEnum) { v = Enum.GetValues(propertyType).Cast <Object>().JoinToString("|"); } } return(p.Item2, $"<{( String.IsNullOrEmpty( v ) ? "value" : v )}>", desc?.Description, req?.Conditional ?? false); }) .ToArray(); var maxLength = allParameters.Max(t => t.Item1.Length + t.Item2.Length + 3); return(allParameters.JoinToString("\n", (p, idx) => $@"{( idx < reqCount ? ( ( p.Item4 ? "+" : "*" ) + " " ) : " " )}{( p.Item1 + " " + p.Item2 ).PadRight( maxLength, ' ' )}{p.Item3}")); }