Browse Source

Ported code from Console.Waterworks.

Note: I have made changes to a few methods due to .Net Core's APIs not matching .Net (full framework). But they are few and far between and the difference is academic here. So, I will not go in to detail. Featurewise, both versions should act the same.
merge-requests/1/head
Craig Oates 6 years ago
parent
commit
9b41e1574f
  1. 11
      CW_Core_Console/ConsoleCommands.cs
  2. 7
      CW_Core_Console/Program.cs
  3. 52
      Console.Waterworks.Core/Assistants/CoOrdinatorAssistant.cs
  4. 106
      Console.Waterworks.Core/Assistants/CommandsAssistant.cs
  5. 15
      Console.Waterworks.Core/Attributes/DescriptionAttribute.cs
  6. 18
      Console.Waterworks.Core/Attributes/ListCommandAttribute.cs
  7. 14
      Console.Waterworks.Core/Attributes/ParametersAttribute.cs
  8. 14
      Console.Waterworks.Core/Attributes/UsageAttribute.cs
  9. 32
      Console.Waterworks.Core/CW_Liaison.cs
  10. 8
      Console.Waterworks.Core/Class1.cs
  11. 96
      Console.Waterworks.Core/CoOrdinators/CoOrdinator.cs
  12. 18
      Console.Waterworks.Core/Constants/CW_Constants.cs
  13. 12
      Console.Waterworks.Core/Loggers/CW_Logger.cs
  14. 77
      Console.Waterworks.Core/Models/Command.cs
  15. 174
      Console.Waterworks.Core/Specialists/CoercionSpecialist.cs
  16. 60
      Console.Waterworks.Core/Specialists/CommandsSpecialist.cs
  17. 67
      Console.Waterworks.Core/Specialists/ConsoleIOSpecialist.cs
  18. 63
      Console.Waterworks.Core/Specialists/HelpSpecialist.cs
  19. 58
      Console.Waterworks.Core/Specialists/ProgramInfoSpecialist.cs

11
CW_Core_Console/ConsoleCommands.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CW_Core_Console
{
public class ConsoleCommands
{
public static string Test() => "Working";
}
}

7
CW_Core_Console/Program.cs

@ -1,4 +1,5 @@
using System;
using Console.Waterworks.Core;
using System;
namespace CW_Core_Console
{
@ -6,7 +7,9 @@ namespace CW_Core_Console
{
static void Main(string[] args)
{
System.Console.WriteLine("Hello World!");
var liaison = new CW_Liaison();
liaison.Run("CW_Core_Console", true);
}
}
}

52
Console.Waterworks.Core/Assistants/CoOrdinatorAssistant.cs

@ -0,0 +1,52 @@
using Console.Waterworks.Core.Constants;
using Console.Waterworks.Core.Loggers;
using Console.Waterworks.Core.Specialists;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Console.Waterworks.Core.Assistants
{
class CoOrdinatorAssistant
{
internal void SetConsoleTitle(CW_Logger logger, ProgramInfoSpecialist progInfoSpec, ConsoleIOSpecialist consoleSpec)
{
logger.LogInfoMessage("Attempting to set console title..");
var title = progInfoSpec.GetProductName();
if (!string.IsNullOrEmpty(title))
{
consoleSpec.SetConsoleTitle(title);
logger.LogSuccessMessage("Console title is now set");
}
else
logger.LogErrorMessage("Unable to determine the program's title. Check the manifest file to make sure it has been set");
}
internal void OutputProgramInfo(CW_Logger logger, ProgramInfoSpecialist progInfoSpec, ConsoleIOSpecialist consoleSpec)
{
logger.LogInfoMessage("Attempting to retrieve program information..");
List<string> programInfo = progInfoSpec.GatherProgramInfomation();
logger.LogInfoMessage($"Found {programInfo.Count} out of {CW_Constants.PROGRAM_INFO_PROPERTIES_COUNT} properties");
logger.LogInfoMessage($"Writing program properties to console..");
consoleSpec.WriteProgramInfo(programInfo);
}
internal void LogCommandGatheringAttempt(List<Type> commandClasses, Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries, CW_Logger logger)
{
logger.LogInfoMessage($"Found {commandClasses.Count} command class(es)..");
logger.LogInfoMessage($"Found {GetFoundCommandsTotal(commandLibraries)} command(s)..");
logger.LogInfoMessage($"Found [{CW_Constants.COMMAND_CLASS_NAME}] class: { commandLibraries.ContainsKey(CW_Constants.COMMAND_CLASS_NAME)}");
logger.LogNoteMessage($"WaterWorks is only looking for the methods in the [{CW_Constants.COMMAND_CLASS_NAME}] class in the specified namespace. Everything else will be ignored");
logger.LogInfoMessage("Program is now initialised and awaiting input from the user. You are welcome ;-)");
}
internal int GetFoundCommandsTotal(Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries)
{
int total = 0;
foreach (var currentClass in commandLibraries.Values)
total += currentClass.Count;
return total;
}
}
}

106
Console.Waterworks.Core/Assistants/CommandsAssistant.cs

@ -0,0 +1,106 @@
using Console.Waterworks.Core.Models;
using Console.Waterworks.Core.Specialists;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Console.Waterworks.Core.Assistants
{
class CommandsAssistant
{
internal bool ValidateClass(Command command, Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries)
=> (commandLibraries.ContainsKey(command.ClassName)) ? true : false;
internal bool ValidateCommand(Command command, Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries)
{
var methodDict = commandLibraries[command.ClassName];
return (methodDict.ContainsKey(command.Name)) ? true : false;
}
internal string ExecuteBadCommandProcedure(Command command, ConsoleIOSpecialist consoleSpec)
{
consoleSpec.WriteErrorSuffix();
return $"The command \'{command.Name}\' is not recognised.";
}
internal bool ValidateParamArguments(Command command, List<ParameterInfo> paramInfoList)
{
var requiredParams = paramInfoList.Where(p => p.IsOptional == false);
var optionalParams = paramInfoList.Where(p => p.IsOptional == true);
int requiredCount = requiredParams.Count();
int optionalCount = optionalParams.Count();
int providedCount = command.Arguments.Count();
return (requiredCount > providedCount) ? false : true;
}
internal string ExecuteMissingArgumentProcedure(Command command, List<ParameterInfo> paramInfoList, ConsoleIOSpecialist consoleSpec)
{
var requiredParams = paramInfoList.Where(p => p.IsOptional == false);
var optionalParams = paramInfoList.Where(p => p.IsOptional == true);
int requiredCount = requiredParams.Count();
int optionalCount = optionalParams.Count();
int providedCount = command.Arguments.Count();
return $"Missing required argument. {requiredCount} required, {optionalCount} optional, {providedCount} provided.";
}
internal List<object> GetParametreValueList(Command command, List<ParameterInfo> paramInfoList)
{
var methodParameterValueList = new List<object>();
if (paramInfoList.Count() > 0)
{
foreach (var param in paramInfoList)
{
methodParameterValueList.Add(param.DefaultValue);
}
for (int i = 0; i < command.Arguments.Count(); i++)
{
var methodParam = paramInfoList.ElementAt(i);
var typeRequired = methodParam.ParameterType;
object value = null;
try
{
value = CoercionSpecialist.CoerceArgument(typeRequired, command.Arguments.ElementAt(i));
methodParameterValueList.RemoveAt(i);
methodParameterValueList.Insert(i, value);
}
catch (ArgumentException ex)
{
string message = $"The value passed for argument '{methodParam.Name}' cannot be parsed to type '{typeRequired.Name}'"; // The exception message is being used instead, for now.
throw new ArgumentException(ex.Message);
}
}
}
return methodParameterValueList;
}
internal Type BuildCommandLibraryClass(Command command, string commandsNamespace)
{
Assembly programAssembly = Assembly.GetEntryAssembly();
Type commandLibraryClass = programAssembly.GetType($"{commandsNamespace}.{command.ClassName}");
return commandLibraryClass;
}
internal string InvokeCommand(Command command, Type typeInfo, object[] inputArguments)
{
try
{
//var result = typeInfo.GetMethod(command.Name).Invoke(command.Name, inputArguments).ToString();
// return result.ToString();
return typeInfo.GetMethod(command.Name).Invoke(command.Name, inputArguments).ToString();
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}
internal object[] GetInputArguments(List<object> methodParametreValueList)
{
object[] inputArguments = null;
if (methodParametreValueList.Count > 0)
inputArguments = methodParametreValueList.ToArray();
return inputArguments;
}
}
}

15
Console.Waterworks.Core/Attributes/DescriptionAttribute.cs

@ -0,0 +1,15 @@
using System;
namespace Console.Waterworks.Core.Attributes
{
[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute
{
public readonly string Description;
public DescriptionAttribute(string description)
{
Description = description;
}
}
}

18
Console.Waterworks.Core/Attributes/ListCommandAttribute.cs

@ -0,0 +1,18 @@
using System;
namespace Console.Waterworks.Core.Attributes
{
[AttributeUsage(AttributeTargets.All)]
public class ListCommandAttribute : Attribute
{
public readonly bool ShowCommand;
public ListCommandAttribute()
{
ShowCommand = true;
}
public ListCommandAttribute(bool show)
{
ShowCommand = show;
}
}
}

14
Console.Waterworks.Core/Attributes/ParametersAttribute.cs

@ -0,0 +1,14 @@
using System;
namespace Console.Waterworks.Core.Attributes
{
[AttributeUsage(AttributeTargets.All)]
public class ParametersAttribute : Attribute
{
public readonly string Parameters;
public ParametersAttribute(string arguments)
{
Parameters = arguments;
}
}
}

14
Console.Waterworks.Core/Attributes/UsageAttribute.cs

@ -0,0 +1,14 @@
using System;
namespace Console.Waterworks.Core.Attributes
{
[AttributeUsage(AttributeTargets.All)]
public class UsageAttribute : Attribute
{
public readonly string UsageExample;
public UsageAttribute(string example)
{
UsageExample = example;
}
}
}

32
Console.Waterworks.Core/CW_Liaison.cs

@ -0,0 +1,32 @@
using Console.Waterworks.Core.CoOrdinators;
namespace Console.Waterworks.Core
{
public class CW_Liaison
{
CoOrdinator _kevin = new CoOrdinator();
/// <summary>
/// Hands control over to Console.Waterworks.Core so the program can "run" as intended.
/// </summary>
/// <param name="consoleCommandsNamespace">The place where the program's command-methods are.</param>
/// <param name="includeProgramInfo">Information about the console program, stated in Assembly Information.</param>
public void Run(string consoleCommandsNamespace,bool includeProgramInfo)
{
_kevin.PrepareConsoleEnvironment();
if (includeProgramInfo == true) _kevin.DisplayProgramInfo();
_kevin.RunProgram(consoleCommandsNamespace);
}
/// <summary>
/// Displays all the attribute information it can find, attached to the command-methods, at run-time.
/// </summary>
/// <remarks>
/// The returned string does not include the "help" information.
/// It returns a string to indicate the method has finished collating the attribute information and displaying the information in the console.
/// This method is intended to be use in a command-method. So, it aims to be compatible with command-method behaviour
/// </remarks>
/// <param name="consoleCommandsNamespace">The location of the programs command-method.</param>
public string RequestHelpDocumentation(string consoleCommandsNamespace) => _kevin.DisplayHelpSection(consoleCommandsNamespace);
}
}

8
Console.Waterworks.Core/Class1.cs

@ -1,8 +0,0 @@
using System;
namespace Console.Waterworks.Core
{
public class Class1
{
}
}

96
Console.Waterworks.Core/CoOrdinators/CoOrdinator.cs

@ -0,0 +1,96 @@
using Console.Waterworks.Core.Assistants;
using Console.Waterworks.Core.Constants;
using Console.Waterworks.Core.Loggers;
using Console.Waterworks.Core.Models;
using Console.Waterworks.Core.Specialists;
using System;
namespace Console.Waterworks.Core.CoOrdinators
{
class CoOrdinator
{
CoOrdinatorAssistant _assistant = new CoOrdinatorAssistant();
ProgramInfoSpecialist _progInfoSpec = new ProgramInfoSpecialist();
ConsoleIOSpecialist _consoleSpec = new ConsoleIOSpecialist();
CommandsSpecialist _commSpec = new CommandsSpecialist();
HelpSpecialist _helpSpec = new HelpSpecialist();
CW_Logger _logger = new CW_Logger();
internal void PrepareConsoleEnvironment()
{
_logger.LogInfoMessage($"Preparing console..");
_consoleSpec.PrepareConsoleEnvironment();
_consoleSpec.SetInputPrompt($"{_progInfoSpec.GetProductName()}> ");
_logger.LogSuccessMessage("Console environment is now setup");
}
internal void DisplayProgramInfo()
{
_logger.LogInfoMessage($"Displaying program information..");
_assistant.SetConsoleTitle(_logger, _progInfoSpec, _consoleSpec);
_assistant.OutputProgramInfo(_logger, _progInfoSpec, _consoleSpec);
}
internal void RunProgram(string commandsNamespace)
{
_logger.LogInfoMessage("Attempting to building commands library..");
var commandClasses = _commSpec.GetCommandClasses(commandsNamespace);
var commandLibraries = _commSpec.GetCommandLibraries(commandClasses);
_assistant.LogCommandGatheringAttempt(commandClasses, commandLibraries, _logger);
while (true)
{
var consoleInput = _consoleSpec.GetInputFromUser();
if (string.IsNullOrEmpty(consoleInput)) continue;
try
{
_logger.LogInfoMessage("Parsing input from user..");
var command = new Command(consoleInput, commandsNamespace, CW_Constants.COMMAND_CLASS_NAME);
_logger.LogInfoMessage("Attempting to execute command..");
var result = _commSpec.ExecuteCommand(commandsNamespace, command, commandClasses, commandLibraries, _consoleSpec);
_consoleSpec.WriteOutputToConsole(result);
_logger.LogSuccessMessage("Command has been executed.");
_logger.LogNoteMessage("An error message does not mean the command did not execute properly or sucessfully.");
}
catch (Exception ex)
{
_logger.LogErrorMessage("Command was not successfully executed. See the error message in console for further details");
_consoleSpec.WriteErrorMessage(ex.Message);
}
_logger.LogInfoMessage("Resetting the console's formatting..");
_logger.LogNoteMessage("This is to make sure no error messages or one-off formating change corrupts the console environment.");
_consoleSpec.ResetConsoleColour();
_logger.LogSuccessMessage("Console's formating has been reset");
}
}
internal string DisplayHelpSection(string commandsNamespace)
{
_logger.LogInfoMessage("Attempting to display help section..");
var commandClasses = _commSpec.GetCommandClasses(commandsNamespace);
if (commandClasses.Count == 0)
{
_logger.LogErrorMessage("Unable to find any help information. Make sure the commands hace the correct atrributes applied");
_consoleSpec.WriteErrorSuffix();
return "Unable to find help information";
}
_logger.LogSuccessMessage("Found help information");
_logger.LogInfoMessage("Attempting to display the help information..");
_consoleSpec.WriteOutputToConsole("Displaying Help section...");
_consoleSpec.LineBreak();
var commandMembers = _helpSpec.GetCommandMembers(commandClasses);
foreach (var command in commandMembers)
{
if (_helpSpec.ListCommand(command) == true)
{
_consoleSpec.WriteOutputToConsole($"Command Name: {command.Name}");
_consoleSpec.WriteOutputToConsole($"Parameters: {_helpSpec.GetParametres(command)}");
_consoleSpec.WriteOutputToConsole($"Description: {_helpSpec.GetDescription(command)}");
_consoleSpec.WriteOutputToConsole($"Example: {_helpSpec.GetUsageExamples(command)}");
_consoleSpec.LineBreak();
}
}
_logger.LogSuccessMessage("Help section displayed in the console");
return "End of Help section.";
}
}
}

18
Console.Waterworks.Core/Constants/CW_Constants.cs

@ -0,0 +1,18 @@
namespace Console.Waterworks.Core.Constants
{
class CW_Constants
{
/// <summary>
/// This represents the maximum number of properties the console can display when the client "DisplayProgramInfo" to true.
/// This is used mostly for logging purposes.
/// </summary>
public const int PROGRAM_INFO_PROPERTIES_COUNT = 4;
/// <summary>
/// This specifies the name of the class Console.Waterworks.Core looks for when it tries to build its command library.
/// This class should not be in Console.Waterworks.Core.
/// It should be in the clients console program.
/// </summary>
public const string COMMAND_CLASS_NAME = "ConsoleCommands";
}
}

12
Console.Waterworks.Core/Loggers/CW_Logger.cs

@ -0,0 +1,12 @@
using System.Diagnostics;
namespace Console.Waterworks.Core.Loggers
{
class CW_Logger
{
internal void LogInfoMessage(string message) => Debug.WriteLine($"[Console.Waterworks.Core] INFO: {message}.");
internal void LogNoteMessage(string message) => Debug.WriteLine($"[Console.Waterworks.Core] NOTE: {message}.");
internal void LogSuccessMessage(string message) => Debug.WriteLine($"[Console.Waterworks.Core] SUCCESS: {message}.");
internal void LogErrorMessage(string message) => Debug.WriteLine($"[Console.Waterworks.Core] ERROR: {message}.");
}
}

77
Console.Waterworks.Core/Models/Command.cs

@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Console.Waterworks.Core.Models
{
class Command
{
public string Name { get; set; }
public string ClassName { get; set; }
List<string> _arguments;
public IEnumerable<string> Arguments
{
get { return _arguments; }
}
/*
* Let us assume the end-user entered: [> Say "Hello, World!" 2].
* The input entered needs to be parse and seperated.
* This is so ClassName and Arguments can be set.
* Once everything has been parsed, _arguments should look like the following,
* _arguments["Hello, World!", "2"] (This will be "mirrored" in Arguments).
* Using the example at the top of this comment block, the end result will look something like,
* ClassName = "Say" | Arguments = ["Hello, World!", "2"]
* This object will then be used as the guide to locate the command-method this model describes.
*/
public Command(string input, string commandsNamespace, string className)
{
var splitInput = Regex.Split(input, "(?<=^[^\"]*(?:\"[^\"]*\"[^\"]*)*) (?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
_arguments = new List<string>();
for (int i = 0; i < splitInput.Length; i++)
{
if (i == 0)
establishCommand(splitInput, i, className);
else
establishArguments(splitInput, i);
}
}
void establishCommand(string[] splitInput, int splitInputLocation, string nameOfClass)
{
Name = splitInput[splitInputLocation];
ClassName = nameOfClass; // The default is "ConsoleCommands.cs"
string[] splitCommandInput = splitInput[0].Split('.');
// This next part is a fancy feature and will almost never be used.
if (splitCommandInput.Length == 2)
{
// In short, it takes something like [> TestClass1.TestMethod2 "Hello, World"].
// And, it isolates the "TestClass1" and TestMethod2" parts.
ClassName = splitCommandInput[0]; // "TestClass1"
Name = splitCommandInput[1]; // TestMethod2"
}
}
void establishArguments(string[] splitInput, int splitInputLocation)
{
var inputArgument = splitInput[splitInputLocation];
string argument = inputArgument;
// This bit is just a check to see if the current part of the input is a quoted string.
// If it is quoted text, "matches" will hold the various parts of the quote.
var regex = new Regex("\"(.*?)\"", RegexOptions.Singleline);
var matches = regex.Match(inputArgument);
if (matches.Captures.Count > 0)
{
// Each part of the quoted text is added to "argument" one-by-one.
// The aim is to add the quoted text as a single line.
var captureQuotedText = new Regex("[^\"]*[^\"]");
var quoted = captureQuotedText.Match(matches.Captures[0].Value);
argument = quoted.Captures[0].Value;
}
_arguments.Add(argument);
}
}
}

174
Console.Waterworks.Core/Specialists/CoercionSpecialist.cs

@ -0,0 +1,174 @@
using System;
namespace Console.Waterworks.Core.Specialists
{
internal static class CoercionSpecialist
{
internal static object CoerceArgument(Type requiredType, string inputValue)
{
var requiredTypeCode = Type.GetTypeCode(requiredType);
string exceptionMessage = $"Cannnot coerce the input argument {inputValue} to required type {requiredType.Name}";
object result = null;
switch (requiredTypeCode)
{
case TypeCode.String:
result = inputValue;
break;
case TypeCode.Int16:
short number16;
if (Int16.TryParse(inputValue, out number16))
{
result = number16;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Int32:
int number32;
if (Int32.TryParse(inputValue, out number32))
{
result = number32;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Int64:
long number64;
if (Int64.TryParse(inputValue, out number64))
{
result = number64;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Boolean:
bool trueFalse;
if (bool.TryParse(inputValue, out trueFalse))
{
result = trueFalse;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Byte:
byte byteValue;
if (byte.TryParse(inputValue, out byteValue))
{
result = byteValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Char:
char charValue;
if (char.TryParse(inputValue, out charValue))
{
result = charValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.DateTime:
DateTime dateValue;
if (DateTime.TryParse(inputValue, out dateValue))
{
result = dateValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Decimal:
Decimal decimalValue;
if (Decimal.TryParse(inputValue, out decimalValue))
{
result = decimalValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Double:
Double doubleValue;
if (Double.TryParse(inputValue, out doubleValue))
{
result = doubleValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Single:
Single singleValue;
if (Single.TryParse(inputValue, out singleValue))
{
result = singleValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.UInt16:
UInt16 uInt16Value;
if (UInt16.TryParse(inputValue, out uInt16Value))
{
result = uInt16Value;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.UInt32:
UInt32 uInt32Value;
if (UInt32.TryParse(inputValue, out uInt32Value))
{
result = uInt32Value;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.UInt64:
UInt64 uInt64Value;
if (UInt64.TryParse(inputValue, out uInt64Value))
{
result = uInt64Value;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
default:
throw new ArgumentException(exceptionMessage);
}
return result;
}
}
}

60
Console.Waterworks.Core/Specialists/CommandsSpecialist.cs

@ -0,0 +1,60 @@
using Console.Waterworks.Core.Assistants;
using Console.Waterworks.Core.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Console.Waterworks.Core.Specialists
{
class CommandsSpecialist
{
CommandsAssistant _assistant = new CommandsAssistant();
internal List<Type> GetCommandClasses(string commandsNameSpace)
{
string theNamespace = commandsNameSpace;
var q = from t in Assembly.GetEntryAssembly().GetTypes()
where t.GetTypeInfo().IsClass && t.Namespace == theNamespace
select t;
return q.ToList();
}
internal Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> GetCommandLibraries(List<Type> commandClasses)
{
var commandLibraries = new Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>>();
foreach (var commandClass in commandClasses)
{
var methods = commandClass.GetMethods(BindingFlags.Static | BindingFlags.Public);
var methodDictionary = new Dictionary<string, IEnumerable<ParameterInfo>>();
foreach (var method in methods)
{
string commandName = method.Name;
methodDictionary.Add(commandName, method.GetParameters());
}
commandLibraries.Add(commandClass.Name, methodDictionary);
}
return commandLibraries;
}
internal string ExecuteCommand(string commandsNamespace, Command command, List<Type> commandClasses, Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries, ConsoleIOSpecialist consoleSpec)
{
var classValidated = _assistant.ValidateClass(command, commandLibraries);
var commandNameValidated = _assistant.ValidateCommand(command, commandLibraries);
Dictionary<string, IEnumerable<ParameterInfo>> methodDictionary;
if (classValidated != true || commandNameValidated != true)
return _assistant.ExecuteBadCommandProcedure(command, consoleSpec);
else
methodDictionary = commandLibraries[command.ClassName];
var paramInfoList = methodDictionary[command.Name].ToList();
var paramsValidated = _assistant.ValidateParamArguments(command, paramInfoList);
if (paramsValidated == false)
return _assistant.ExecuteMissingArgumentProcedure(command, paramInfoList, consoleSpec);
var methodParametreValueList = _assistant.GetParametreValueList(command, paramInfoList);
var typeInfo = _assistant.BuildCommandLibraryClass(command, commandsNamespace);
var inputArguments = _assistant.GetInputArguments(methodParametreValueList);
var result = _assistant.InvokeCommand(command, typeInfo, inputArguments);
return result;
}
}
}

67
Console.Waterworks.Core/Specialists/ConsoleIOSpecialist.cs

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
namespace Console.Waterworks.Core.Specialists
{
class ConsoleIOSpecialist
{
string _consolePrompt;
internal void PrepareConsoleEnvironment()
{
#if DEBUG
System.Console.BackgroundColor = ConsoleColor.DarkGray;
System.Console.Clear();
System.Console.ForegroundColor = ConsoleColor.White;
System.Console.WriteLine(" ------------ ");
System.Console.WriteLine("| DEBUG MODE |");
System.Console.WriteLine(" ------------ ");
#endif
}
internal void SetConsoleTitle(string title) => System.Console.Title = title;
internal void SetInputPrompt(string prompt) => _consolePrompt = prompt;
internal void WriteProgramInfo(List<string> programInfo)
{
foreach (var line in programInfo)
{
if (!string.IsNullOrEmpty(line)) System.Console.WriteLine(line);
}
}
internal string GetInputFromUser()
{
System.Console.ForegroundColor = ConsoleColor.Green;
System.Console.Write(_consolePrompt);
System.Console.ResetColor();
return System.Console.ReadLine();
}
internal void WriteOutputToConsole(string message) => System.Console.WriteLine(message);
internal void LineBreak() => System.Console.WriteLine();
internal void WriteErrorSuffix()
{
System.Console.ForegroundColor = ConsoleColor.Red;
System.Console.Write("[ERROR] ");
}
internal void WriteErrorMessage(string message)
{
System.Console.ForegroundColor = ConsoleColor.Red;
System.Console.WriteLine($"[ERROR] {message}");
System.Console.ResetColor();
}
internal void ResetConsoleColour() => System.Console.ResetColor();
internal void WriteInfoSuffix()
{
System.Console.ForegroundColor = ConsoleColor.Yellow;
System.Console.Write("[INFO] ");
}
}
}

63
Console.Waterworks.Core/Specialists/HelpSpecialist.cs

@ -0,0 +1,63 @@
using Console.Waterworks.Core.Attributes;
using Console.Waterworks.Core.Loggers;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Console.Waterworks.Core.Specialists
{
class HelpSpecialist
{
CW_Logger _logger = new CW_Logger();
internal MemberInfo[] GetCommandMembers(List<Type> commandClasses) => commandClasses[0].GetMembers();
internal bool ListCommand(MemberInfo command)
{
var customAttributes = GetCustomAttributes(command);
var castedAttributes = CheckForAttributesType<ListCommandAttribute>(customAttributes);
return (castedAttributes != null) ? castedAttributes.ShowCommand : false;
}
T CheckForAttributesType<T>(object[] attributes)
{
T theAttributes = default(T);
for (int i = 0; i < attributes.Length; i++)
{
try
{
theAttributes = (T)attributes[i];
break;
}
catch (Exception)
{
_logger.LogInfoMessage("The attempted casting attempt failed. Do not panic. This was expected");
}
}
return theAttributes;
}
object[] GetCustomAttributes(MemberInfo command) => command.GetCustomAttributes(true) as object[];
internal object GetParametres(MemberInfo command)
{
var attributes = GetCustomAttributes(command);
var castedAttributes = CheckForAttributesType<ParametersAttribute>(attributes);
return (castedAttributes != null) ? castedAttributes.Parameters : "Parameters values could not be found";
}
internal object GetDescription(MemberInfo command)
{
var attributes = GetCustomAttributes(command);
var castedAttributes = CheckForAttributesType<DescriptionAttribute>(attributes);
return (castedAttributes != null) ? castedAttributes.Description : "Description could not be found";
}
internal object GetUsageExamples(MemberInfo command)
{
var attributes = GetCustomAttributes(command);
var castedAttributes = CheckForAttributesType<UsageAttribute>(attributes);
return (castedAttributes != null) ? castedAttributes.UsageExample : "Example could not be found";
}
}
}

58
Console.Waterworks.Core/Specialists/ProgramInfoSpecialist.cs

@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Console.Waterworks.Core.Specialists
{
class ProgramInfoSpecialist
{
internal List<string> GatherProgramInfomation()
{
var info = new List<string>()
{
addProductLine(),
addCompanyLine(),
addCopyRightLine(),
addProductDescription()
};
return info;
}
private string addCopyRightLine()
{
var assembly = Assembly.GetEntryAssembly();
var copyRightAttribute = assembly.GetCustomAttributes<AssemblyCopyrightAttribute>().FirstOrDefault();
return copyRightAttribute?.Copyright;
}
string addProductLine()
{
var name = GetProductName();
var buildInfo = getBuildInfo();
return (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(buildInfo)) ? $"{name} {buildInfo}" : null;
}
string addCompanyLine()
{
var assembly = Assembly.GetEntryAssembly();
var companyAttribute = assembly.GetCustomAttributes<AssemblyCompanyAttribute>().FirstOrDefault();
return companyAttribute?.Company;
}
string addProductDescription()
{
var assembly = Assembly.GetEntryAssembly();
var descriptionAttribute = assembly.GetCustomAttributes<AssemblyDescriptionAttribute>().FirstOrDefault();
return descriptionAttribute?.Description;
}
internal string GetProductName()
{
var assembly = Assembly.GetEntryAssembly();
var productAttribute = assembly.GetCustomAttributes<AssemblyProductAttribute>().FirstOrDefault();
return productAttribute?.Product;
}
string getBuildInfo() => Assembly.GetEntryAssembly().GetName().Version.ToString();
}
}
Loading…
Cancel
Save