Browse Source
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
19 changed files with 892 additions and 10 deletions
@ -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"; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -1,8 +0,0 @@
|
||||
using System; |
||||
|
||||
namespace Console.Waterworks.Core |
||||
{ |
||||
public class Class1 |
||||
{ |
||||
} |
||||
} |
@ -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."; |
||||
} |
||||
} |
||||
} |
@ -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"; |
||||
} |
||||
} |
@ -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}."); |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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] "); |
||||
} |
||||
} |
||||
} |
@ -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"; |
||||
} |
||||
} |
||||
} |
@ -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…
Reference in new issue