Пример #1
0
    /// <summary>
    /// Implementation of the abstract base function 'Validate'.
    /// </summary>
    /// <param name="propertyMetaInfo"></param>
    /// <param name="parameterObject"></param>     
    public override void Validate(PropertyMetaInfo propertyMetaInfo, ParameterBase parameterObject)
    {
      MethodBase? methodBase = MethodBase.GetCurrentMethod();
      //
      // Make sure the 'ValidationAttribute' is assigned to the right 
      // property type. (A string in this case)
      //
#pragma warning disable CS8604
      if (propertyMetaInfo.Type.ToLower().IndexOf("string") < 0)
      {
        propertyMetaInfo.ValidationError = new ValidationError(propertyMetaInfo, propertyMetaInfo.PropertyInfo.GetValue(parameterObject)?.ToString(), $"The attribute '{methodBase?.DeclaringType}' is not allowed on properties of type: '{propertyMetaInfo.Type}'.");
        return;
      }

      //
      // The actual validation.
      //
      if (propertyMetaInfo.PropertyInfo.GetValue(parameterObject)?.ToString()?.Length < this.MinLength)
      {
        propertyMetaInfo.ValidationError = new ValidationError(propertyMetaInfo, propertyMetaInfo.PropertyInfo.GetValue(parameterObject)?.ToString(), $"{ValidationErrorMessage}");
        return;
      }
#pragma warning restore CS8604

      //
      // The validation passed.
      //
      propertyMetaInfo.ValidationError = null;
    }
Пример #2
0
    /// <summary>
    /// Creates a summary of the validation errors of the parameter object 
    /// provided in argument 'parameterObject'.
    /// <para>
    /// The message provided in argument 'message' will be shown on top of the summary.
    /// </para>
    /// <para>
    /// The summary will be returned as a string with a line length matching with the 
    /// value of argument screenWidth.
    /// </para>
    /// <para>
    /// The result string is supposed to be rendered on the command line.
    /// </para>
    /// </summary>
    /// <param name="parameterObject"></param>
    /// <param name="message"></param>
    /// <param name="screenWidth"></param>
    /// <returns>The resulting string</returns>
    public virtual String CreateValidationSummary(ParameterBase parameterObject, string message = "One or more of the command line arguments are invalid.", int screenWidth = 80)
    {
      string result;
      result = String.Empty;

      if (parameterObject == null)
      {
        return result;
      }

      result = CreateValidationSummaryMessage(message, screenWidth);
      result += CreateValidationSummaryBody(parameterObject, screenWidth);
      return result;
    }
Пример #3
0
    /// <summary>
    /// Processes the command line by calling the parse and validation
    /// function. 
    /// <para>
    /// If the 'showUsageOnEmptyArgs' argument is true and the 'args' 
    /// argument has no argument which qualifies as parameter argument, 
    /// the usage screen will be rendered to the console error stream
    /// and the return value will be false;
    /// </para>
    /// <para>
    /// If the validation fails because it was a help request, the
    /// help screen will be rendered to the console standard stream
    /// and the return value will be false.
    /// </para>
    /// <para>
    /// If the validation fails because it was a version request, the
    /// version screen will be rendered to the console standard stream
    /// and the return value will be false.
    /// </para>
    /// <para>
    /// If the validation fails because of invalid arguments, the
    /// validation summary screen will be rendered to the console error
    /// stream the return value will be false.
    /// </para>
    /// <para>
    /// The function returns true if the process was successful and 
    /// no screen was rendered.
    /// </para>
    /// </summary>
    /// <param name="args">
    /// The command line arguments which will be processed.
    /// </param>
    /// <param name="showUsageOnEmptyArgs">
    /// Determines whether the usage screen will be rendered if the 
    /// args array has no argument which qualifies as parameter argument.
    /// </param>
    /// <returns>true, if the process succeeded, otherwise false</returns>
    public virtual bool Process(String[] args, bool showUsageOnEmptyArgs = true)
    {
      bool IsValid;
      string output;

      this.Parse(args);

      //
      // The usage screen will be rendered to the 
      // console error stream.
      //
      if (!this.IsHelpRequest && !this.IsVersionRequest && showUsageOnEmptyArgs && this.Arguments.Count() == 0)
      {
        output = this.CreateUsage();
        ParameterBase.PrintToConsole(output, consoleOutputStream : ConsoleOutputStream.ERROR);
        return false;
      }

      IsValid = this.Validate();

      if (!IsValid)
      {
        if (this.IsHelpRequest)
        {
          output = this.CreateHelp();
          Console.Write(output);
          return IsValid;
        }
        if (this.IsVersionRequest)
        {
          output = this.CreateVersion(this);
          Console.Write(output);
          return IsValid;
        }
        output = this.CreateValidationSummary();
        //ParameterBase.PrintToConsole(output, ConsoleColor.Red);

        //
        // The validation summary screen will be rendered to the 
        // console error stream.
        //
        ParameterBase.PrintToConsole(output, consoleOutputStream: ConsoleOutputStream.ERROR, foregroundColor: ConsoleColor.Red);
        return IsValid;
      }
      return IsValid;
    }
Пример #4
0
    /// <summary>
    /// Creates a usage description for the command associated with the provided
    /// 'parameterObject'. 
    /// <para>
    /// The usage description is either the one provided with
    /// the 'UsageAttribute' or a generic description created from the known 
    /// parameter attributes.
    /// </para>
    /// <para>
    /// The result string is supposed to be rendered on the command line.
    /// </para>
    /// </summary>
    /// <param name="parameterObject"></param>
    /// <param name="screenWidth"></param>
    /// <returns>The resulting string</returns>
    public virtual string CreateUsage(ParameterBase parameterObject, int screenWidth = 80)
    {
      string result;
      string usage;

      result = String.Empty;

      result += CreateUsageHeader(screenWidth);
      result += "Usage:\r\n\r\n";
      UsageAttribute? usageAttribute = (UsageAttribute?)parameterObject.GetType().GetCustomAttribute(typeof(UsageAttribute));

      //
      // If a usage description is provided in the command attributes return that description.
      //
      if ((usageAttribute != null) && !String.IsNullOrWhiteSpace(usageAttribute.Usage))
      {
        usage = usageAttribute.Usage;
      }
      //
      // Create a usage description from the known parameter attributes.
      //
      else
      {
        usage = parameterObject.CommandName + " ";
        usage += "[" + parameterObject.HelpIndicatorList.First() + "] ";
        usage += "[" + parameterObject.VersionIndicatorList.First() + "] ";
        foreach (var metaInfo in parameterObject.PropertyMetaInfoList)
        {
          if (metaInfo.IsMandatory)
          {
            usage += metaInfo.Name + "=" + "<" + metaInfo.Type + "> ";
          }
          else
          {
            usage += "[" + metaInfo.Name + "=" + "<" + metaInfo.Type + ">" + "] ";
          }
        }
      }
      
      List<string> lines = CreateWrappedLines(usage, screenWidth, 0);
      return result + String.Join("\r\n", lines);
    }
Пример #5
0
    /// <summary>
    /// Implementation of the abstract base function 'Validate'.
    /// </summary>
    /// <param name="propertyMetaInfo"></param>
    /// <param name="parameterObject"></param>     
    public override void Validate(PropertyMetaInfo propertyMetaInfo, ParameterBase parameterObject)
    {
      MethodBase? methodBase = MethodBase.GetCurrentMethod();

#pragma warning disable CS8600, CS8602, CS8604

      var propertyValue = propertyMetaInfo.PropertyInfo.GetValue(parameterObject);
      if(propertyValue == null)
      {
        propertyMetaInfo.ValidationError = new ValidationError(propertyMetaInfo, propertyMetaInfo.PropertyInfo.GetValue(parameterObject)?.ToString(), $"{ValidationErrorMessage}");
        return;
      }
      else
      {
      
        switch(propertyMetaInfo.Type)
        {
          case "UInt16|Null":
          case "UInt16":
          case "Int16|Null":
          case "Int16":
          {      
            if(Convert.ToInt16(this.MaxValue) >= ((Int16) propertyValue))
            {
              propertyMetaInfo.ValidationError = null;
              return;
            }
            break;
          }
          case "UInt32|Null":
          case "UInt32":
          case "Int32|Null":
          case "Int32":
          {
            if(((Int32) this.MaxValue) >= ((Int32) propertyValue))
            {
              propertyMetaInfo.ValidationError = null;
              return;
            }
            break;
          }
          case "UInt64|Null":
          case "UInt64":
          case "Int64|Null":
          case "Int64":
          {
            if(Convert.ToInt64(this.MaxValue) >= ((Int64) propertyValue))
            {
              propertyMetaInfo.ValidationError = null;
              return;
            }
            break;
          }
          case "Single|Null":
          case "Single":
          {
            if(Convert.ToSingle(this.MaxValue) >= ((Single) propertyValue))
            {
              propertyMetaInfo.ValidationError = null;
              return;
            }
            break;
          }
          case "Double|Null":
          case "Double":
          {
            if(((Double) this.MaxValue) >= ((Double) propertyValue))
            {
              propertyMetaInfo.ValidationError = null;
              return;
            }
            break;
          }
          case "Decimal|Null":
          case "Decimal":
          {
            if(Convert.ToDecimal(this.MaxValue) >= ((Decimal) propertyValue))
            {
              propertyMetaInfo.ValidationError = null;
              return;
            }
            break;
          }
          default:
          {
            //
            // The 'ValidationAttribute' is assigned to the wrong
            // property type. (Must be one of the number types above)
            //

            propertyMetaInfo.ValidationError = new ValidationError(propertyMetaInfo, propertyMetaInfo.PropertyInfo.GetValue(parameterObject)?.ToString(), $"The attribute '{methodBase?.DeclaringType}' is not allowed on properties of type: '{propertyMetaInfo.Type}'.");
            return;
          }
        }
        propertyMetaInfo.ValidationError =  new ValidationError(propertyMetaInfo, propertyMetaInfo.PropertyInfo.GetValue(parameterObject)?.ToString(), $"{ValidationErrorMessage}");
      }

#pragma warning restore CS8600, CS8602, CS8604
    }
Пример #6
0
        public void ParameterBase_ConstructorTest()
        {
            ParameterBase parameter = new ParameterBase("ParameterBaseTest", Assembly.GetExecutingAssembly(), new DisplayHelper());

            Assert.IsNotNull(parameter, "The 'Parameter' constructor should return a valid instance.");
        }
Пример #7
0
 /// <summary>
 /// This function must be implemented by every subclass.
 /// <para>
 /// The function must set the 'propertyMetaInfo.ValidationError' property if the validation failed.
 /// </para>
 /// <para>
 /// If the validation succeeded, the 'propertyMetaInfo.ValidationError' should be set to 'null'.
 /// </para>
 /// <example> <para>An example string length validation attribute implementation:</para>
 /// <code>
 ///  public class MaxStringLengthAttribute : ValidationAttributeBase
 ///  {
 ///    public int MaxLength
 ///    {
 ///      get;
 ///      private set;
 ///    }
 ///
 ///    public MaxStringLengthAttribute(int maxLength, string validationErrorMessage) : base(validationErrorMessage)
 ///    {
 ///       this.MaxLength = maxLength;
 ///       this.ValidationErrorMessage = validationErrorMessage;
 ///    }
 ///
 ///    //
 ///    // Create an implementation of the abstact base function 'Validate'
 ///    //
 ///    public override void Validate(PropertyMetaInfo propertyMetaInfo, ParameterBase parameterObject)
 ///    {
 ///      MethodBase? methodBase = MethodBase.GetCurrentMethod();
 ///      //
 ///      // Make sure the 'ValidationAttribute' is assigned to the right
 ///      // property type. (A string in this case)
 ///      //
 ///      if(propertyMetaInfo.Type.ToLower().IndexOf("string") &lt; 0)
 ///      {
 ///        propertyMetaInfo.ValidationError = new ValidationError(propertyMetaInfo, propertyMetaInfo.PropertyInfo.GetValue(parameterObject)?.ToString(), $"The attribute '{methodBase?.DeclaringType}' is not allowed on properties of type: '{propertyMetaInfo.Type}'.");
 ///        return;
 ///      }
 ///
 ///      //
 ///      // The actual validation. Set the 'ValidationError' if the validation fails.
 ///      //
 ///      if(propertyMetaInfo.PropertyInfo.GetValue(parameterObject)?.ToString()?.Length &gt; this.MaxLength)
 ///      {
 ///        propertyMetaInfo.ValidationError = new ValidationError(propertyMetaInfo, propertyMetaInfo.PropertyInfo.GetValue(parameterObject)?.ToString(), $"{ValidationErrorMessage}");
 ///        return;
 ///      }
 ///
 ///      //
 ///      // The validation passed. Clear the 'ValidationError'.
 ///      //
 ///      propertyMetaInfo.ValidationError = null;
 ///    }
 ///
 ///  }// END class
 /// </code>
 /// </example>
 /// </summary>
 /// <param name="propertyMetaInfo"></param>
 /// <param name="parameterObject"></param>
 public abstract void Validate(PropertyMetaInfo propertyMetaInfo, ParameterBase parameterObject);
Пример #8
0
    const char Asterisk = '*'; // *


    // ************************************************************************
    // IDisplayHelper implementation START
    // ************************************************************************

    /// <summary>
    /// Creates the help screen for the parameter object provided in argument 
    /// 'parameterObject'. 
    /// <para>
    /// The line length of the resulting help text will match with value provide in argument 'screenWidth'
    /// as long a the value is greater than the minimum screen line length. Otherwise the minimum screen
    /// line length will be used.
    /// </para>
    /// <para>
    /// The result string is supposed to be rendered on the command line.
    /// </para>
    /// </summary>
    /// <param name="parameterObject"></param>
    /// <param name="screenWidth"></param>
    /// <returns>The resulting string</returns>
    public virtual string CreateHelp(ParameterBase parameterObject, int screenWidth = 80)
    {
      string result;
      int longestArgumentLength;
      int longestTypeLength;
      int longestDefaultLength;
      string help;
      List<string> helpLines;

      result = string.Empty;
      longestArgumentLength = 0;

      if (parameterObject == null)
      {
        return result;
      }

      HelpAttribute? helpAttribute = (HelpAttribute?)parameterObject.GetType().GetCustomAttribute(typeof(HelpAttribute));

      //
      // If a help text is provided in the command attributes show that text first.
      //
      if ((helpAttribute != null) && !String.IsNullOrWhiteSpace(helpAttribute.Help))
      {
        help = helpAttribute.Help;
      }
      else
      {
        help = string.Empty;
      }


      if (parameterObject.PropertyMetaInfoList.Count == 0)
      {
        result = "The current parameter object has no parameter property!";
      }
      else
      {

        longestArgumentLength = parameterObject.PropertyMetaInfoList.Max(item => item.Name.Length);
        longestTypeLength = parameterObject.PropertyMetaInfoList.Max(item => item.Type.Length);
        longestDefaultLength = parameterObject.PropertyMetaInfoList.Max(item => (item.DefaultValue?.ToString()?.Length ?? 0));

        longestArgumentLength = Math.Max(longestArgumentLength, "[Parameter]".Length); // [Parameter] = 11 characters min
        longestTypeLength = Math.Max(longestTypeLength, "[Type]".Length); // [Type] = 6 characters min 
        longestDefaultLength = Math.Max(longestDefaultLength, "[Default]".Length); // [Default] = 9 characters min

        //
        // Expand the screen width if there isn't at least 20 characters left for the description.
        // Minimum length for the help screen is 11 + 6 + 9 + 20 for parameter, type default and description
        // plus additional 15 characters for spaces and borders. That is 61 characters minimum.
        //
        if((longestArgumentLength + longestTypeLength + longestDefaultLength + 20) > screenWidth)
        {
          screenWidth = (longestArgumentLength + longestTypeLength + longestDefaultLength + 20);
        }

        if(!String.IsNullOrWhiteSpace(help))
        {
          //
          // Format the help text from the help attribute.
          //
          helpLines = CreateWrappedLines(help, screenWidth, leadingSpaces:0, keepEmptyLines:true);
          result += "\r\n" + String.Join("\r\n", helpLines) + "\r\n\r\n";
        }
        

        result += CreateHelpHeader(screenWidth);

        result += CreateHelpTop(screenWidth, longestArgumentLength, longestTypeLength, longestDefaultLength);

        result += CreateHelpAndVersionArgumentHelpLines(parameterObject.HelpIndicatorList.First(), "Shows the help screen. (This screen).", screenWidth, longestArgumentLength, longestTypeLength, longestDefaultLength);
        result += CreateHelpSeparatorLine(screenWidth, longestArgumentLength, longestTypeLength, longestDefaultLength);
        result += CreateHelpAndVersionArgumentHelpLines(parameterObject.VersionIndicatorList.First(), "Shows the command version number if available or an empty string. (Nothing)", screenWidth, longestArgumentLength, longestTypeLength, longestDefaultLength);
        result += CreateHelpSeparatorLine(screenWidth, longestArgumentLength, longestTypeLength, longestDefaultLength);

        for (int index = 0; index < parameterObject.PropertyMetaInfoList.Count; index++)
        {
          result += CreateHelpLines(parameterObject.PropertyMetaInfoList[index], screenWidth, longestArgumentLength, longestTypeLength, longestDefaultLength);
          if (index < parameterObject.PropertyMetaInfoList.Count - 1)
          {
            result += CreateHelpSeparatorLine(screenWidth, longestArgumentLength, longestTypeLength, longestDefaultLength);
          }
        }

        result += CreateHelpBottom(screenWidth, longestArgumentLength, longestTypeLength, longestDefaultLength);
      }
      result += "\r\n\r\n";
      result += CreateUsage(parameterObject);

      return result;
    }
Пример #9
0
    private static string CreateValidationSummaryBody(ParameterBase parameterObject, int screenWidth)
    {
      string result;
      int longestArgumentLength;
      int errorMessageSpace;

      //╔═[Argument]═╦═[Error message]════════════════════════════════════════════════════════╗
      //║_abcdefg_.  ║_abcdefghijklmnop_......................................................║
      //╚════════════╩════════════════════════════════════════════════════════════════════════╝
      //             |--------------------     errorMessageSpace     -------------------------|

      //
      // Create top with column names
      //
      longestArgumentLength = parameterObject.ValidationErrorList.Max(item => item.PropertyMetaInfo.Name.Length);
      longestArgumentLength = Math.Max(longestArgumentLength, "[Argument]".Length);
      errorMessageSpace = screenWidth - longestArgumentLength - 5; // screenWidth - longestArgumentLength - 2xSPACE -3x║
      result = string.Empty;
      result += CornerTopLeft;

      result += HorizontalLine + "[Argument]" + new string(HorizontalLine, longestArgumentLength - "[Argument]".Length) + HorizontalLine;
      result += TJunctionUp;
      result += HorizontalLine + "[Error message]" + new string(HorizontalLine, errorMessageSpace - "[Error message]".Length - 1);
      result += CornerTopRight + "\r\n";

      for (int index = 0; index < parameterObject.ValidationErrorList.Count; index++)
      {
        //
        // Create line
        //
        string argumentName = parameterObject.ValidationErrorList[index].PropertyMetaInfo.Name;
        string errorMessage = parameterObject.ValidationErrorList[index].PropertyMetaInfo.ValidationError?.Message ?? "";
        List<string> errorMessageLines = CreateWrappedLines(errorMessage, errorMessageSpace - 1);
        result += VerticalLine;
        result += " " + argumentName + new string(' ', longestArgumentLength - argumentName.Length) + " ";
        result += VerticalLine;
        result += errorMessageLines[0] + " ";
        result += VerticalLine + "\r\n";

        if (errorMessageLines.Count > 1)
        {
          for (int linesIndex = 1; linesIndex < errorMessageLines.Count; linesIndex++)
          {
            result += VerticalLine;
            result += " " + new string(' ', longestArgumentLength) + " ";
            result += VerticalLine;
            result += errorMessageLines[linesIndex] + " ";
            result += VerticalLine + "\r\n";
          }
        }

        if (index < parameterObject.ValidationErrorList.Count - 1)
        {
          //
          // Create separator
          //
          result += TJunctionLeft;
          result += new string(HorizontalLine, longestArgumentLength + 2);
          result += CrossJunction;
          result += new string(HorizontalLine, errorMessageSpace);
          result += TJunctionRight + "\r\n";
        }
      }

      //
      // Create bottom
      //
      result += CornerBottomLeft;
      result += new string(HorizontalLine, longestArgumentLength + 2);
      result += TJunctionDown;
      result += new string(HorizontalLine, errorMessageSpace);
      result += CornerBottomRight + "\r\n";

      return result;
    }