diff --git a/src/InterAppConnector/Argument.cs b/src/InterAppConnector/Argument.cs
index e85c204..7b2bbf7 100644
--- a/src/InterAppConnector/Argument.cs
+++ b/src/InterAppConnector/Argument.cs
@@ -2,6 +2,7 @@
using System.Reflection;
using InterAppConnector.Attributes;
using InterAppConnector.DataModels;
+using System.Linq;
namespace InterAppConnector
{
@@ -97,31 +98,6 @@ public bool HasParameterAValue(string name)
return hasValue;
}
- ///
- /// Get the first entry of the custom attribute with the type in , if exists,
- /// otherwise return
- ///
- /// The type of the attribute to find
- /// The name of the parameter
- /// The first entry of the attribute with type , otherwise
- public ParameterType GetCustomAttribute(string parameterName) where ParameterType : Attribute
- {
- ParameterType parameter = null;
-
- if (IsParameterDefined(parameterName))
- {
- foreach (object item in _parameters[parameterName].Attributes)
- {
- if (item.GetType() == typeof(ParameterType) && parameter == null)
- {
- parameter = (ParameterType)item;
- }
- }
- }
-
- return parameter;
- }
-
///
/// Get the first alias assigned to the property or the property name if no aliases were found.
/// It returns if the property does not belong to the argument defined in
@@ -136,7 +112,7 @@ public ParameterType GetCustomAttribute(string parameterName) whe
PropertyInfo? propertyFound = typeof(ArgumentType).GetProperty(propertyName);
if (propertyFound != null)
{
- if (propertyFound.GetCustomAttributes().Count() > 0)
+ if (propertyFound.GetCustomAttributes().Any())
{
argumentName = propertyFound.GetCustomAttributes().First().Name;
}
@@ -180,7 +156,7 @@ protected Argument ParseInternal(string[] arguments, string argumentPrefixes)
{
string argument = argumentList.Dequeue();
- /**
+ /*
* An argument must not be a number.
* However, there may be cases where you want to pass a negative number in an argument
* In this case, the string is considered a value of the latest argument declared at that time
@@ -189,7 +165,7 @@ protected Argument ParseInternal(string[] arguments, string argumentPrefixes)
if (IsArgumentWithPrefix(argument, argumentPrefixes))
{
double number;
-
+
if (double.TryParse(argument, out number))
{
if (descriptor != null && descriptor.Value == null)
@@ -257,17 +233,17 @@ public static Argument Parse(dynamic arguments, string argumentPrefix)
Argument result = new Argument();
List argumentList = new List();
ExpandoObject args = arguments;
- foreach (KeyValuePair item in args)
+ foreach (var item in from KeyValuePair item in args
+ where item.Value is not null
+ select item)
{
- if (item.Value is not null)
+ argumentList.Add(argumentPrefix + item.Key);
+ if (item.Value is not bool)
{
- argumentList.Add(argumentPrefix + item.Key);
- if (item.Value is not bool)
- {
- argumentList.Add(item.Value.ToString());
- }
+ argumentList.Add(item.Value.ToString());
}
}
+
return result.ParseInternal(argumentList.ToArray(), argumentPrefix);
}
@@ -275,13 +251,13 @@ protected static bool IsArgumentWithPrefix(string argument, string argumentPrefi
{
bool isArgumentWithPrefix = false;
string[] argumentPrefixList = argumentPrefixes.Split(",");
- foreach (string argumentPrefix in argumentPrefixList)
+ foreach (var _ in from string argumentPrefix in argumentPrefixList
+ where argument.ToLower().StartsWith(argumentPrefix.ToLower())
+ select new { })
{
- if (argument.ToLower().StartsWith(argumentPrefix.ToLower()))
- {
- isArgumentWithPrefix = true;
- }
+ isArgumentWithPrefix = true;
}
+
return isArgumentWithPrefix;
}
}
diff --git a/src/InterAppConnector/CommandManager.cs b/src/InterAppConnector/CommandManager.cs
index 7986b34..fa07646 100644
--- a/src/InterAppConnector/CommandManager.cs
+++ b/src/InterAppConnector/CommandManager.cs
@@ -2,11 +2,10 @@
using InterAppConnector.DataModels;
using InterAppConnector.Exceptions;
using InterAppConnector.Interfaces;
-using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
-using System.Text.RegularExpressions;
+using System.Linq;
[assembly: InternalsVisibleTo("InterAppConnector.Test.Library")]
namespace InterAppConnector
@@ -20,6 +19,16 @@ public class CommandManager
internal Dictionary _arguments = new Dictionary();
internal Dictionary _parameterObject = new Dictionary();
internal string _result = "";
+
+ private static ICommand? _currentCommand;
+
+ internal static ICommand? CurrentCommand
+ {
+ get
+ {
+ return _currentCommand;
+ }
+ }
internal string? GetActionKeyByActions(List actions)
{
@@ -29,12 +38,18 @@ where item.Value.Action.Intersect(actions).Any()
return commandName;
}
+ internal static void SetCommand(ICommand command)
+ {
+ _currentCommand = command;
+ }
+
internal CommandManager SetArguments(List actions, List argument)
{
string? selectedCommand = GetActionKeyByActions(actions);
-
if (selectedCommand != default)
{
+ SetCommand(_commands[selectedCommand]);
+ object currentParameterObject = _parameterObject[selectedCommand];
foreach (ParameterDescriptor item in argument)
{
ParameterDescriptor? findArgument = (from value in _arguments[selectedCommand].Arguments.Values
@@ -44,213 +59,42 @@ where value.Name.ToLower().Trim() == item.Name.ToLower().Trim()
if (findArgument != default(ParameterDescriptor))
{
- ParameterDescriptor modifiedValues = _arguments[selectedCommand].Arguments[findArgument.Name];
- Type? parameterType = Nullable.GetUnderlyingType(modifiedValues.ParameterType);
- if (parameterType == null)
+ List distinctAttributes = RuleManager.GetDistinctAttributes(findArgument.Attributes);
+ List rulesToExecute = RuleManager.GetAssemblyRules(typeof(CommandManager));
+
+ foreach (Attribute attribute in distinctAttributes)
{
- parameterType = modifiedValues.ParameterType;
+ rulesToExecute = RuleManager.MergeRules(rulesToExecute, RuleManager.GetAssemblyRules(findArgument.ParameterType));
}
- if (parameterType.IsEnum)
+ foreach (var rule in from IArgumentSettingRule rule in rulesToExecute
+ where rule.IsRuleEnabledInArgumentSetting(currentParameterObject.GetType().GetProperty(findArgument.OriginalPropertyName)!)
+ select rule)
{
/*
- * Remember that a value in an enumeration may have different aliases that works
- * like aliases in properties, with the main difference that refers to a value instead of
- * the property.
- * Aliases can indentify a value uniquely and could mask the original value name, but be careful for batch execution, where the value
- * passed to the property is also the name of the property
+ * A default rule does not have an interface with an argument type,
+ * so you have to consider also this case
*/
- try
+ if (RuleManager.IsSpecializedRule(rule))
{
- _arguments[selectedCommand].Arguments[findArgument.Name].Value = EnumHelper.GetEnumerationFieldByValue(parameterType, item.Value.ToString());
- _parameterObject[selectedCommand].GetType().GetProperty(findArgument.OriginalPropertyName)!.SetValue(_parameterObject[selectedCommand], EnumHelper.GetEnumerationFieldByValue(parameterType, item.Value.ToString()));
- _arguments[selectedCommand].Arguments[findArgument.Name].IsSetByUser = true;
- }
- catch (ArgumentException exc)
- {
- /*
- * If something went wrong with the parse of the value, throw an exception.
- * You may need to change this exception with a more specialized exception,
- * but the InnerException property should contain the exception raised by
- * EnumHelper.GetFieldName()
- */
- throw new ArgumentException("The value provided in parameter " + item.Name + " is not acceptable. Please provide a new value", item.Name, exc);
- }
- }
- else if ((parameterType.IsClass || StructHelper.IsStruct(parameterType)) && parameterType != typeof(string))
- {
- /*
- * If the parameter is a value, the value is directly assigned to the parameter.
- * But what about a class that receives a custom InputString as his parameter?
- * Generally speaking, the command class may have only one method between the constructor that
- * receive a string as argument and the Parse method
- * Don't forget that there is also the case when CustomInputStringAttribute is not assigned
- * or there is a custom method that needs to be used
- * There should be only one and one method with this attribute, and if more methods are found that have this attribute
- * raise a DuplicateObjectException exception
- * A string is a class, so you have to treat it as a special object.
- * What about parameters that are structs, for example in the case of Guid? Actually check only if it is a struct,
- * so check if the type is a value type and it is not an enumeration and a primitive
- */
+ Type argumentType = rule.GetType().GetInterface(typeof(IArgumentSettingRule<>).FullName!)!.GetGenericArguments()[0];
- if (_arguments[selectedCommand].GetCustomAttribute(findArgument.Name) == null)
- {
- List methodsWithCustomInputStringAttribute = (from method in parameterType.GetMethods()
- where method.GetCustomAttribute() != null
- select method).ToList();
- if (methodsWithCustomInputStringAttribute.Count < 2)
- {
- if (methodsWithCustomInputStringAttribute.Count == 0)
- {
- // Check if there is a constructor that accepts a string as parameter
- ConstructorInfo? constructor = parameterType.GetConstructor(new[] { typeof(string) });
- if (constructor != null)
- {
- try
- {
- _arguments[selectedCommand].Arguments[findArgument.Name].Value = constructor.Invoke(new[] { item.Value });
- _parameterObject[selectedCommand].GetType().GetProperty(findArgument.OriginalPropertyName)!.SetValue(_parameterObject[selectedCommand], constructor.Invoke(new[] { item.Value }));
- _arguments[selectedCommand].Arguments[findArgument.Name].IsSetByUser = true;
- }
- catch (Exception exc)
- {
- throw new ArgumentException("The value provided to argument " + item.Name + " is not acceptable. Reason: " + exc.GetBaseException().Message, item.Name, exc.InnerException);
- }
- }
- else
- {
- throw new MethodNotFoundException(parameterType.Name, "Cannot find a public constructor that accepts a string as parameter in class " + parameterType.Name);
- }
- }
- else
- {
- if (methodsWithCustomInputStringAttribute[0].GetParameters().Length == 1)
- {
- if (methodsWithCustomInputStringAttribute[0].GetParameters()[0].ParameterType == typeof(string))
- {
- try
- {
- _arguments[selectedCommand].Arguments[findArgument.Name].Value = methodsWithCustomInputStringAttribute[0].Invoke(null, new[] { item.Value })!;
- _parameterObject[selectedCommand].GetType().GetProperty(findArgument.OriginalPropertyName)!.SetValue(_parameterObject[selectedCommand], methodsWithCustomInputStringAttribute[0].Invoke(null, new[] { item.Value }));
- _arguments[selectedCommand].Arguments[findArgument.Name].IsSetByUser = true;
- }
- catch (Exception exc)
- {
- throw new ArgumentException("The value provided to argument " + item.Name + " is not acceptable. Reason: " + exc.GetBaseException().Message, item.Name, exc.InnerException);
- }
- }
- else
- {
- throw new TypeMismatchException(typeof(string).FullName!, methodsWithCustomInputStringAttribute[0].GetParameters()[0].ParameterType.FullName!, "", "Error in argument definition. It is expected a string, but the actual type is " + methodsWithCustomInputStringAttribute[0].GetParameters()[0].ParameterType.FullName);
- }
- }
- else
- {
- throw new TypeMismatchException(typeof(string).FullName!, "More than 1 parameter", "", "Error in argument definition. It is expected one parameter of type string, but the method has multiple parameters.");
- }
- }
- }
- else
- {
- throw new DuplicateObjectException(methodsWithCustomInputStringAttribute[1].Name, new List { "[CustomInputString] attribute" }, methodsWithCustomInputStringAttribute[0].Name, "Error in class " + parameterType.Name + ". It is expected that only one method may have the [CustomInputString] attribute, but there are " + methodsWithCustomInputStringAttribute.Count + " methods with this attribute");
- }
- }
- else
- {
- if (string.IsNullOrEmpty(_arguments[selectedCommand].GetCustomAttribute(findArgument.Name).StringFormat))
- {
- try
- {
- // Do not use the ParseExact method. Use the constructor with the parameter as value
- _arguments[selectedCommand].Arguments[findArgument.Name].Value = parameterType.GetConstructor(new[] { typeof(string) })!.Invoke(new[] { item.Value });
- _parameterObject[selectedCommand].GetType().GetProperty(findArgument.OriginalPropertyName)!.SetValue(_parameterObject[selectedCommand], parameterType.GetConstructor(new[] { typeof(string) })!.Invoke(new[] { item.Value }));
- _arguments[selectedCommand].Arguments[findArgument.Name].IsSetByUser = true;
- }
- catch (Exception exc)
- {
- throw new ArgumentException("The value provided to argument " + item.Name + " is not acceptable. Reason: " + exc.GetBaseException().Message, item.Name, exc.InnerException);
- }
- }
- else
- {
- try
- {
- // Use ParseExact method
- _arguments[selectedCommand].Arguments[findArgument.Name].Value = parameterType.GetMethod("ParseExact", new[] {typeof(string), typeof(string), typeof(IFormatProvider)})!.Invoke(null, new[] { item.Value, _arguments[selectedCommand].GetCustomAttribute(findArgument.Name).StringFormat, CultureInfo.InvariantCulture })!;
- _parameterObject[selectedCommand].GetType().GetProperty(findArgument.OriginalPropertyName)!.SetValue(_parameterObject[selectedCommand], parameterType.GetMethod("ParseExact", new[] { typeof(string), typeof(string), typeof(IFormatProvider) })!.Invoke(null, new[] { item.Value, _parameterObject[selectedCommand].GetType().GetProperty(findArgument.OriginalPropertyName)!.GetCustomAttribute()!.StringFormat, CultureInfo.InvariantCulture }));
- _arguments[selectedCommand].Arguments[findArgument.Name].IsSetByUser = true;
- }
- catch (Exception exc)
- {
- throw new ArgumentException("The value provided to argument " + item.Name + " is not acceptable. Reason: " + exc.GetBaseException().Message, item.Name, exc.InnerException);
- }
- }
- }
- }
- else
- {
- try
- {
- /*
- * During the parse of the arguments, if an argument is passed without a value is considered a switch
- * This is not always true, especially if the argument is placed as last token in the argument definition
- * So if the type of the argument is not a boolean, you have to specify a value explicitly
- */
- if (parameterType != typeof(bool) && item.Value.GetType() != typeof(bool))
- {
- _arguments[selectedCommand].Arguments[findArgument.Name].Value = Convert.ChangeType(item.Value, parameterType);
- _parameterObject[selectedCommand].GetType().GetProperty(findArgument.OriginalPropertyName)!.SetValue(_parameterObject[selectedCommand], Convert.ChangeType(item.Value, parameterType));
- _arguments[selectedCommand].Arguments[findArgument.Name].IsSetByUser = true;
- }
- else
- {
- if (parameterType == typeof(bool))
- {
- _arguments[selectedCommand].Arguments[findArgument.Name].Value = Convert.ChangeType(item.Value, parameterType);
- _parameterObject[selectedCommand].GetType().GetProperty(findArgument.OriginalPropertyName)!.SetValue(_parameterObject[selectedCommand], Convert.ChangeType(item.Value, parameterType));
- _arguments[selectedCommand].Arguments[findArgument.Name].IsSetByUser = true;
- }
- else
- {
- throw new ArgumentException();
- }
- }
- }
- catch (Exception exc)
- {
- throw new ArgumentException("The value provided to argument " + item.Name + " is not acceptable. Please provide a valid value", item.Name, exc);
- }
- }
-
- if (_arguments[selectedCommand].GetCustomAttribute(findArgument.Name) != null)
- {
- ValueValidatorAttribute validator = _arguments[selectedCommand].GetCustomAttribute(findArgument.Name);
-
- if (validator.ValueValidatorType.GetInterface(typeof(IValueValidator).Name) != null)
- {
- IValueValidator valueValidator = (IValueValidator) Activator.CreateInstance(validator.ValueValidatorType)!;
- bool customValidationErrorMessageMissing = false;
+ Attribute? attributeExists = (from distinctAttribute in distinctAttributes
+ where distinctAttribute.GetType() == argumentType
+ select distinctAttribute).FirstOrDefault();
- try
+ if (attributeExists != default(Attribute))
{
- if (!valueValidator.ValidateValue(_arguments[selectedCommand].Arguments[findArgument.Name].Value))
- {
- customValidationErrorMessageMissing = true;
- }
+ findArgument = rule.SetArgumentValueIfTypeExists(currentParameterObject, currentParameterObject.GetType().GetProperty(findArgument.OriginalPropertyName)!, findArgument, item);
}
- catch(Exception exc)
- {
- throw new ArgumentException("The value provided to argument " + item.Name + " is not acceptable. Reason: " + exc.GetBaseException().Message, item.Name, exc.InnerException);
- }
-
- if (customValidationErrorMessageMissing)
+ else
{
- throw new ArgumentException("The value provided to argument " + item.Name + " is not valid according to the validation procedure");
+ findArgument = rule.SetArgumentValueIfTypeDoesNotExist(currentParameterObject, currentParameterObject.GetType().GetProperty(findArgument.OriginalPropertyName)!, findArgument, item);
}
}
else
{
- throw new TypeMismatchException(typeof(IValueValidator).Name, "", "", validator.ValueValidatorType.Name + " doesn't have an interface of type " + typeof(IValueValidator).Name);
+ findArgument = rule.SetArgumentValueIfTypeExists(currentParameterObject, currentParameterObject.GetType().GetProperty(findArgument.OriginalPropertyName)!, findArgument, item);
}
}
}
@@ -287,12 +131,12 @@ where method.GetCustomAttribute() != null
throw new MultipleCommandNotAllowedException(command.GetType().FullName!, command.GetType().FullName + " has multiple ICommand class implemented. An action may have only one ICommand implementation");
}
- string className = command.GetType().FullName;
+ string className = command.GetType().FullName!;
if (!_commands.ContainsKey(className))
{
_commands.Add(className, command);
_parameterObject.Add(className, parameterObject);
-
+ SetCommand(command);
Argument argument = new Argument();
if (command.GetType().GetCustomAttribute() != null)
@@ -315,112 +159,62 @@ where string.Join(" ", item.Value.Action) == string.Join(" ", argument.Action)
foreach (PropertyInfo parameterProperty in parameterObject.GetType().GetProperties())
{
- if (parameterProperty.GetCustomAttribute() == null)
- {
- ParameterDescriptor descriptor = new ParameterDescriptor();
- descriptor.OriginalPropertyName = parameterProperty.Name;
+ List distinctAttributes = RuleManager.GetDistinctAttributes(parameterProperty);
+ ParameterDescriptor descriptor = new ParameterDescriptor();
+ List rulesToExecute = RuleManager.GetAssemblyRules(typeof(CommandManager));
- Type? parameterType = Nullable.GetUnderlyingType(parameterProperty.PropertyType);
+ foreach (Attribute attribute in distinctAttributes)
+ {
+ rulesToExecute = RuleManager.MergeRules(rulesToExecute, RuleManager.GetAssemblyRules(parameterProperty.PropertyType));
+ }
- if (parameterType == null)
- {
- descriptor.ParameterType = parameterProperty.PropertyType;
- }
- else
+ foreach (var rule in from IArgumentDefinitionRule rule in rulesToExecute
+ where rule.IsRuleEnabledInArgumentDefinition(parameterProperty)
+ select rule)
+ {
+ if (RuleManager.IsSpecializedRule(rule))
{
- descriptor.ParameterType = parameterType;
- }
+ Type argumentType = rule.GetType().GetInterface(typeof(IArgumentDefinitionRule<>).FullName!)!.GetGenericArguments()[0];
- List
public static uint MaximumObjectDepth { get; set; } = 64;
- internal static string DescribeCommands(CommandManager commandManager, bool writeHeader = true, bool simulateConsoleException = false)
+ internal static string DescribeCommands(CommandManager CommandManager, bool writeHeader = true, bool simulateConsoleException = false)
{
StringBuilder description = new StringBuilder();
int lineLength;
@@ -50,9 +50,9 @@ internal static string DescribeCommands(CommandManager commandManager, bool writ
{
description.AppendLine(DrawLine(lineLength));
description.AppendLine();
- description.Append(Assembly.GetEntryAssembly().GetName().Name);
+ description.Append(Assembly.GetEntryAssembly()!.GetName().Name);
description.Append(" ");
- description.AppendLine(Assembly.GetEntryAssembly().GetName().Version.ToString());
+ description.AppendLine(Assembly.GetEntryAssembly()!.GetName().Version!.ToString());
description.AppendLine();
description.AppendLine(DrawLine(lineLength));
}
@@ -60,19 +60,19 @@ internal static string DescribeCommands(CommandManager commandManager, bool writ
description.AppendLine("Available actions:");
description.AppendLine();
- foreach (KeyValuePair item in commandManager._arguments)
+ foreach (KeyValuePair item in CommandManager._arguments)
{
string action;
string actionDescription = "No description provided";
- if (commandManager._commands[item.Key].GetType().GetCustomAttribute() != null)
+ if (CommandManager._commands[item.Key].GetType().GetCustomAttribute() != null)
{
- action = commandManager._commands[item.Key].GetType().GetCustomAttribute().Name;
- actionDescription = commandManager._commands[item.Key].GetType().GetCustomAttribute().Description;
+ action = CommandManager._commands[item.Key].GetType().GetCustomAttribute().Name;
+ actionDescription = CommandManager._commands[item.Key].GetType().GetCustomAttribute().Description;
}
else
{
- action = commandManager._commands[item.Key].GetType().Name.ToLower().Trim();
+ action = CommandManager._commands[item.Key].GetType().Name.ToLower().Trim();
}
description.AppendLine(DescribeAction(action, actionDescription, item.Value.Arguments.Values.ToList()));
@@ -113,15 +113,7 @@ internal static string DescribeAction(string action, string actionDescription, L
description.Append(" (optional) : ");
}
- if (!string.IsNullOrEmpty(descriptor.Description))
- {
- description.AppendLine(descriptor.Description);
- }
- else
- {
- description.AppendLine("No description provided");
- }
-
+ description.AppendLine(descriptor.Description);
// for enumerations, describe the numbers and values that a parameter may have
if (descriptor.ParameterType.IsEnum)
@@ -136,15 +128,7 @@ internal static string DescribeAction(string action, string actionDescription, L
description.Append("(");
description.Append(possibleValue.Value);
description.Append(") : ");
- if (string.IsNullOrEmpty(possibleValue.Description))
- {
- description.Append("No description provided");
- }
- else
- {
- description.Append(possibleValue.Description);
- }
-
+ description.Append(possibleValue.Description);
description.AppendLine();
if (possibleValue.Aliases.Count > 1)
@@ -168,7 +152,7 @@ internal static string DescribeAction(string action, string actionDescription, L
}
else
{
- /**
+ /*
* For other types, we have three cases:
* - no validators are defined
* - no examples are defined
diff --git a/src/InterAppConnector/EnumHelper.cs b/src/InterAppConnector/EnumHelper.cs
index 0683cfd..0db9f0c 100644
--- a/src/InterAppConnector/EnumHelper.cs
+++ b/src/InterAppConnector/EnumHelper.cs
@@ -1,9 +1,7 @@
-using InterAppConnector.Attributes;
-using InterAppConnector.DataModels;
+using InterAppConnector.DataModels;
using InterAppConnector.Exceptions;
-using System.ComponentModel;
+using InterAppConnector.Interfaces;
using System.Reflection;
-using System.Text.RegularExpressions;
namespace InterAppConnector
{
@@ -13,62 +11,56 @@ public class EnumHelper
internal void LoadEnumerationValues() where EnumType : Enum
{
- foreach (FieldInfo item in typeof(EnumType).GetFields())
+ Type argumentBaseType = typeof(EnumType);
+ foreach (FieldInfo item in argumentBaseType.GetFields())
{
// take only the value defined by the user
if (!item.IsSpecialName)
{
- if (item.GetCustomAttribute() == null)
+ List distinctAttributes = RuleManager.GetDistinctAttributes(item);
+ ParameterDescriptor descriptor = new ParameterDescriptor();
+ List rulesToExecute = RuleManager.GetAssemblyRules(typeof(CommandManager));
+
+ foreach (Attribute attribute in distinctAttributes)
{
- ParameterDescriptor descriptor = new ParameterDescriptor();
- descriptor.OriginalPropertyName = item.Name;
+ rulesToExecute = RuleManager.MergeRules(rulesToExecute, RuleManager.GetAssemblyRules(item.DeclaringType!));
+ }
- if (item.GetCustomAttributes().Count() > 0)
+ foreach (var rule in from IArgumentDefinitionRule rule in rulesToExecute
+ where rule.IsRuleEnabledInArgumentDefinition(item)
+ select rule)
+ {
+ try
{
- foreach (AliasAttribute alias in item.GetCustomAttributes())
+ Type argumentType = rule.GetType().GetInterface(typeof(IArgumentDefinitionRule<>).FullName!)!.GetGenericArguments()[0];
+
+ Attribute? attributeExists = (from attributeItem in distinctAttributes
+ where attributeItem.GetType() == argumentType
+ select attributeItem).FirstOrDefault();
+
+ if (attributeExists != default(Attribute))
{
- if (!string.IsNullOrWhiteSpace(alias.Name))
- {
- double number;
- if (!double.TryParse(alias.Name.ToLower().Trim(), out number))
- {
- if (Regex.IsMatch(alias.Name.ToLower().Trim(), @"^[A-Za-z0-9-]+$", RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1)))
- {
- descriptor.Aliases.Add(alias.Name.ToLower().Trim());
- }
- else
- {
- throw new ArgumentException("Invalid string found in " + alias.Name + ". Alias must contain only alphanumeric characters and hyphens (-). Null values, empty string and numbers are also not allowed");
- }
- }
- else
- {
- throw new ArgumentException("Invalid alias found in " + item.Name + ". The alias cannot be null, an empty string or a number", item.Name);
- }
- }
- else
- {
- throw new ArgumentException("Invalid alias found in " + item.Name + ". The alias cannot be null, an empty string or a number", item.Name);
- }
+ descriptor = rule.DefineArgumentIfTypeExists(argumentBaseType, item, descriptor);
+ }
+ else
+ {
+ descriptor = rule.DefineArgumentIfTypeDoesNotExist(argumentBaseType, item, descriptor);
}
-
- descriptor.Name = descriptor.Aliases[0].ToLower().Trim();
- //descriptor.Aliases.RemoveAt(0);
- }
- else
- {
- descriptor.Name = item.Name.ToLower().Trim();
}
-
- if (item.GetCustomAttribute() != null)
+ catch
{
- descriptor.Description = item.GetCustomAttribute().Description;
+ /*
+ * A default rule does not have an interface with an argument type,
+ * so you have to consider also this case
+ */
+ descriptor = rule.DefineArgumentIfTypeExists(argumentBaseType, item, descriptor);
}
+ }
- descriptor.Value = (int)item.GetValue(typeof(EnumType));
-
+ if (!string.IsNullOrEmpty(descriptor.Name))
+ {
_parameters.Add(item.Name.ToLower().Trim(), descriptor);
- }
+ }
}
}
}
@@ -84,33 +76,9 @@ internal void LoadEnumerationValues(Type enumType)
* Moreover, as the LoadEnumerationValues is internal to this class and it is not public,
* it is necessary the BindingFlags attributes in order to invoke the method
*/
- typeof(EnumHelper).GetMethod("LoadEnumerationValues", BindingFlags.Instance | BindingFlags.NonPublic, Type.EmptyTypes).MakeGenericMethod(enumType).Invoke(this, null);
- }
- catch (Exception exc)
- {
- throw exc.InnerException;
- }
- }
- else
- {
- throw new TypeMismatchException(typeof(Enum).FullName, enumType.GetType().FullName, null, enumType.GetType().FullName + " is not an enumeration");
- }
- }
-
- ///
- /// Get the enumeration field associated with the value
- ///
- /// The enum type
- /// The value to search in the enumeration
- /// The enumeration value
- /// Exception raised when the type chosen is not an enumeration
- public static object GetEnumerationFieldByValue(Type enumType, string value)
- {
- if (enumType.IsEnum)
- {
- try
- {
- return typeof(EnumHelper).GetMethod("GetEnumerationFieldByValue", 1, new[] { typeof(string) }).MakeGenericMethod(enumType).Invoke(null, new object[] { value });
+ #pragma warning disable S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
+ typeof(EnumHelper).GetMethod("LoadEnumerationValues", BindingFlags.Instance | BindingFlags.NonPublic, Type.EmptyTypes)!.MakeGenericMethod(enumType).Invoke(this, null);
+ #pragma warning restore S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
}
catch (Exception exc)
{
@@ -119,7 +87,7 @@ public static object GetEnumerationFieldByValue(Type enumType, string value)
}
else
{
- throw new TypeMismatchException(typeof(Enum).FullName, enumType.GetType().FullName, null, enumType.GetType().FullName + " is not an enumeration");
+ throw new TypeMismatchException(typeof(Enum).FullName!, enumType.FullName!, null!, enumType.FullName + " is not an enumeration");
}
}
@@ -152,6 +120,32 @@ public static string GetFieldName(string fieldName) where EnumType : E
return enumValue;
}
+ ///
+ /// Get the enumeration field associated with the value
+ ///
+ /// The enum type
+ /// The value to search in the enumeration
+ /// The enumeration value
+ /// Exception raised when the type chosen is not an enumeration
+ public static object GetEnumerationFieldByValue(Type enumType, string value)
+ {
+ if (enumType.IsEnum)
+ {
+ try
+ {
+ return typeof(EnumHelper).GetMethod("GetEnumerationFieldByValue", 1, new[] { typeof(string) })!.MakeGenericMethod(enumType).Invoke(null, new object[] { value })!;
+ }
+ catch (Exception exc)
+ {
+ throw exc.InnerException!;
+ }
+ }
+ else
+ {
+ throw new TypeMismatchException(typeof(Enum).FullName!, enumType.FullName!, null!, enumType.FullName + " is not an enumeration");
+ }
+ }
+
///
/// Get the enumeration value by searching for his value and alias
///
@@ -165,7 +159,6 @@ public static EnumType GetEnumerationFieldByValue(string value) where
helper.LoadEnumerationValues();
int parsedNumber;
- object enumType;
string stringToEvaluate = "";
foreach (ParameterDescriptor descriptor in helper._parameters.Values)
@@ -174,7 +167,7 @@ public static EnumType GetEnumerationFieldByValue(string value) where
{
if ((int) descriptor.Value == parsedNumber)
{
- stringToEvaluate += parsedNumber;
+ stringToEvaluate = parsedNumber.ToString();
}
}
else
@@ -198,14 +191,6 @@ public static EnumType GetEnumerationFieldByValue(string value) where
if (!string.IsNullOrEmpty(stringToEvaluate))
{
- /*if (Enum.TryParse(typeof(EnumType), stringToEvaluate, true, out enumType))
- {
- if (Enum.IsDefined(typeof(EnumType), enumType))
- {
- return (EnumType)enumType;
- }
- }*/
-
/**
* The checks and the validations done might be enough to ensure that
* the value belongs to the enumeration type, so the Parse method should not
diff --git a/src/InterAppConnector/Interfaces/IArgumentDefinitionRule.cs b/src/InterAppConnector/Interfaces/IArgumentDefinitionRule.cs
new file mode 100644
index 0000000..66fc4fe
--- /dev/null
+++ b/src/InterAppConnector/Interfaces/IArgumentDefinitionRule.cs
@@ -0,0 +1,14 @@
+namespace InterAppConnector.Interfaces
+{
+ ///
+ /// Interface that can be used in order to define rules for a particular attribute or object
+ ///
+ /// The type
+ public interface IArgumentDefinitionRule : IArgumentDefinitionRule
+ {
+ virtual bool ReturnTrue(RuleType type)
+ {
+ return true;
+ }
+ }
+}
diff --git a/src/InterAppConnector/Interfaces/IArgumentDefinitionRuleBase.cs b/src/InterAppConnector/Interfaces/IArgumentDefinitionRuleBase.cs
new file mode 100644
index 0000000..6753088
--- /dev/null
+++ b/src/InterAppConnector/Interfaces/IArgumentDefinitionRuleBase.cs
@@ -0,0 +1,58 @@
+using InterAppConnector.DataModels;
+using System.Reflection;
+
+namespace InterAppConnector.Interfaces
+{
+ public interface IArgumentDefinitionRule
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, FieldInfo field, ParameterDescriptor descriptor);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor descriptor);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor descriptor);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor descriptor);
+
+ ///
+ /// Define if the rule should be executed or not
+ ///
+ ///
+ ///
+ public bool IsRuleEnabledInArgumentDefinition(PropertyInfo property);
+
+ ///
+ /// Define if the rule should be executed or not
+ ///
+ ///
+ ///
+ public bool IsRuleEnabledInArgumentDefinition(FieldInfo field);
+ }
+}
diff --git a/src/InterAppConnector/Interfaces/IArgumentSettingRule.cs b/src/InterAppConnector/Interfaces/IArgumentSettingRule.cs
new file mode 100644
index 0000000..5f9ba4f
--- /dev/null
+++ b/src/InterAppConnector/Interfaces/IArgumentSettingRule.cs
@@ -0,0 +1,10 @@
+namespace InterAppConnector.Interfaces
+{
+ public interface IArgumentSettingRule : IArgumentSettingRule
+ {
+ virtual bool ReturnTrue(RuleType type)
+ {
+ return true;
+ }
+ }
+}
diff --git a/src/InterAppConnector/Interfaces/IArgumentSettingRuleBase.cs b/src/InterAppConnector/Interfaces/IArgumentSettingRuleBase.cs
new file mode 100644
index 0000000..f4a90c5
--- /dev/null
+++ b/src/InterAppConnector/Interfaces/IArgumentSettingRuleBase.cs
@@ -0,0 +1,63 @@
+using InterAppConnector.DataModels;
+using System.Reflection;
+
+namespace InterAppConnector.Interfaces
+{
+ public interface IArgumentSettingRule
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor);
+
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool IsRuleEnabledInArgumentSetting(PropertyInfo property);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool IsRuleEnabledInArgumentSetting(FieldInfo field);
+ }
+}
diff --git a/src/InterAppConnector/RuleManager.cs b/src/InterAppConnector/RuleManager.cs
new file mode 100644
index 0000000..34c3093
--- /dev/null
+++ b/src/InterAppConnector/RuleManager.cs
@@ -0,0 +1,102 @@
+using InterAppConnector.Interfaces;
+using System.Reflection;
+
+namespace InterAppConnector
+{
+ public static class RuleManager
+ {
+ internal static List GetDistinctAttributes(PropertyInfo property)
+ {
+ List attributes = new List();
+
+ foreach (Attribute attribute in property.GetCustomAttributes())
+ {
+ Attribute? findAttribute = (from item in attributes
+ where item.GetType().FullName == attribute.GetType().FullName
+ select item).FirstOrDefault();
+
+ if (findAttribute == default(Attribute))
+ {
+ attributes.Add(attribute);
+ }
+ }
+
+ return attributes;
+ }
+
+ internal static List GetDistinctAttributes(FieldInfo property)
+ {
+ List attributes = new List();
+
+ foreach (Attribute attribute in property.GetCustomAttributes())
+ {
+ Attribute? findAttribute = (from item in attributes
+ where item.GetType().FullName == attribute.GetType().FullName
+ select item).FirstOrDefault();
+
+ if (findAttribute == default(Attribute))
+ {
+ attributes.Add(attribute);
+ }
+ }
+
+ return attributes;
+ }
+
+ internal static List GetDistinctAttributes(List rawAttributeList)
+ {
+ List attributes = new List();
+
+ foreach (Attribute attribute in rawAttributeList)
+ {
+ Attribute? findAttribute = (from item in attributes
+ where item.GetType() == attribute.GetType()
+ select item).FirstOrDefault();
+
+ if (findAttribute == default(Attribute))
+ {
+ attributes.Add(attribute);
+ }
+ }
+
+ return attributes;
+ }
+
+ internal static List GetAssemblyRules(Type assemblyType)
+ {
+ List rules = new List();
+
+ foreach (Type currentType in assemblyType.Assembly.ExportedTypes)
+ {
+ if (currentType.GetInterface(typeof(RuleType).FullName!) != null
+ && !currentType.ContainsGenericParameters && !currentType.IsInterface)
+ {
+ rules.Add((RuleType)Activator.CreateInstance(currentType)!);
+ }
+ }
+
+ return rules;
+ }
+
+ internal static List MergeRules(List initialRules, List rulesToMerge)
+ {
+ List resultingRules = initialRules;
+
+ List additionalRules = (from item in rulesToMerge
+ where !resultingRules.Contains(item)
+ select item).ToList();
+
+ return resultingRules.Union(additionalRules).ToList();
+ }
+
+ internal static bool IsSpecializedRule(IArgumentDefinitionRule rule)
+ {
+ return (from item in rule.GetType().GetInterfaces() where item.FullName!.StartsWith(typeof(IArgumentDefinitionRule<>).FullName!) select item).Any();
+ }
+
+ internal static bool IsSpecializedRule(IArgumentSettingRule rule)
+ {
+ return (from item in rule.GetType().GetInterfaces() where item.FullName!.StartsWith(typeof(IArgumentSettingRule<>).FullName!) select item).Any();
+ }
+ }
+}
diff --git a/src/InterAppConnector/Rules/AliasRule.cs b/src/InterAppConnector/Rules/AliasRule.cs
new file mode 100644
index 0000000..baef4e9
--- /dev/null
+++ b/src/InterAppConnector/Rules/AliasRule.cs
@@ -0,0 +1,98 @@
+using InterAppConnector.Attributes;
+using InterAppConnector.DataModels;
+using InterAppConnector.Interfaces;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+namespace InterAppConnector.Rules
+{
+ public class AliasRule : IArgumentDefinitionRule
+ {
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ descriptor.Name = property.Name.ToLower().Trim();
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor descriptor)
+ {
+ descriptor.Name = property.Name.ToLower().Trim();
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ foreach (string name in property.GetCustomAttributes().Select(x => x.Name))
+ {
+ if (Regex.IsMatch(name, @"^[A-Za-z0-9-]+$", RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1)))
+ {
+ if (!descriptor.Aliases.Contains(name.ToLower().Trim()))
+ {
+ descriptor.Aliases.Add(name.ToLower().Trim());
+ }
+ }
+ else
+ {
+ throw new ArgumentException("Invalid string found in " + property.Name + ". Alias must contain only alphanumeric characters and hyphens (-). Null values or empty string are also not allowed");
+ }
+ }
+
+ descriptor.Name = property.GetCustomAttributes().First().Name.ToLower().Trim();
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, FieldInfo field, ParameterDescriptor descriptor)
+ {
+ foreach (string name in field.GetCustomAttributes().Select(x => x.Name))
+ {
+ if (!string.IsNullOrWhiteSpace(name))
+ {
+ double number;
+ if (!double.TryParse(name.ToLower().Trim(), out number)
+ && Regex.IsMatch(name.ToLower().Trim(), @"^[A-Za-z0-9-]+$", RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1)))
+ {
+ if (!descriptor.Aliases.Contains(name.ToLower().Trim()))
+ {
+ descriptor.Aliases.Add(name.ToLower().Trim());
+ }
+ }
+ else
+ {
+ throw new ArgumentException("Invalid alias found in " + field.Name + ". The alias must contain alphanumerical characters and hypens. It cannot be null, an empty string or a number", field.Name);
+ }
+ }
+ else
+ {
+ throw new ArgumentException("Invalid alias found in " + field.Name + ". The alias cannot be null, an empty string or a number", field.Name);
+ }
+ }
+
+ descriptor.Name = descriptor.Aliases[0].ToLower().Trim();
+ return descriptor;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(PropertyInfo property)
+ {
+ bool isRuleEnabled = true;
+
+ if (property.GetCustomAttribute() != null)
+ {
+ isRuleEnabled = false;
+ }
+
+ return isRuleEnabled;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(FieldInfo field)
+ {
+ bool isRuleEnabled = true;
+
+ if (field.GetCustomAttribute() != null)
+ {
+ isRuleEnabled = false;
+ }
+
+ return isRuleEnabled;
+ }
+ }
+}
diff --git a/src/InterAppConnector/Rules/CustomInputStringRule.cs b/src/InterAppConnector/Rules/CustomInputStringRule.cs
new file mode 100644
index 0000000..650bf20
--- /dev/null
+++ b/src/InterAppConnector/Rules/CustomInputStringRule.cs
@@ -0,0 +1,138 @@
+using InterAppConnector.Attributes;
+using InterAppConnector.DataModels;
+using InterAppConnector.Exceptions;
+using InterAppConnector.Interfaces;
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+namespace InterAppConnector.Rules
+{
+ public class CustomInputStringRule : IArgumentSettingRule
+ {
+ public bool IsRuleEnabledInArgumentSetting(PropertyInfo property)
+ {
+ /*
+ * If the parameter is a value, the value is directly assigned to the parameter.
+ * But what about a class that receives a custom InputString as his parameter?
+ * Generally speaking, the command class may have only one method between the constructor that
+ * receive a string as argument and the Parse method
+ * Don't forget that there is also the case when CustomInputStringAttribute is not assigned
+ * or there is a custom method that needs to be used
+ * There should be only one and one method with this attribute, and if more methods are found that have this attribute
+ * raise a DuplicateObjectException exception
+ * A string is a class, so you have to treat it as a special object.
+ * What about parameters that are structs, for example in the case of Guid? Actually check only if it is a struct,
+ * so check if the type is a value type and it is not an enumeration and a primitive
+ */
+ Type? parameterType = Nullable.GetUnderlyingType(property.PropertyType);
+ if (parameterType == null)
+ {
+ parameterType = property.PropertyType;
+ }
+ return (parameterType.IsClass || StructHelper.IsStruct(parameterType)) && parameterType != typeof(string);
+ }
+
+ public bool IsRuleEnabledInArgumentSetting(FieldInfo field)
+ {
+ return false;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ return argumentDescriptor;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ List methodsWithCustomInputStringAttribute = (from method in argumentDescriptor.ParameterType.GetMethods()
+ where method.GetCustomAttribute() != null
+ select method).ToList();
+ switch (methodsWithCustomInputStringAttribute.Count)
+ {
+ case 0:
+ // Check if there is a constructor that accepts a string as parameter
+ ConstructorInfo? constructor = argumentDescriptor.ParameterType.GetConstructor(new[] { typeof(string) });
+ if (constructor != null)
+ {
+ try
+ {
+ argumentDescriptor.Value = constructor.Invoke(new[] { userValueDescriptor.Value });
+ property.SetValue(parentObject, argumentDescriptor.Value);
+ argumentDescriptor.IsSetByUser = true;
+ }
+ catch (Exception exc)
+ {
+ throw new ArgumentException("The value provided to argument " + userValueDescriptor.Name + " is not acceptable. Reason: " + exc.GetBaseException().Message, userValueDescriptor.Name, exc.InnerException);
+ }
+ }
+ else
+ {
+ throw new MethodNotFoundException(property.PropertyType.Name, "Cannot find a public constructor that accepts a string as parameter in class " + property.PropertyType.Name);
+ }
+ break;
+ case 1:
+ if (methodsWithCustomInputStringAttribute[0].GetParameters().Length != 1)
+ {
+ throw new TypeMismatchException(typeof(string).FullName!, "More than 1 parameter", "", "Error in argument definition. It is expected one parameter of type string, but the method has multiple parameters.");
+ }
+
+ if (methodsWithCustomInputStringAttribute[0].GetParameters()[0].ParameterType == typeof(string))
+ {
+ try
+ {
+ argumentDescriptor.Value = methodsWithCustomInputStringAttribute[0].Invoke(null, new[] { userValueDescriptor.Value })!;
+ property.SetValue(parentObject, argumentDescriptor.Value);
+ argumentDescriptor.IsSetByUser = true;
+ }
+ catch (Exception exc)
+ {
+ throw new ArgumentException("The value provided to argument " + userValueDescriptor.Name + " is not acceptable. Reason: " + exc.GetBaseException().Message, userValueDescriptor.Name, exc.InnerException);
+ }
+ }
+ else
+ {
+ throw new TypeMismatchException(typeof(string).FullName!, methodsWithCustomInputStringAttribute[0].GetParameters()[0].ParameterType.FullName!, "", "Error in argument definition. It is expected a string, but the actual type is " + methodsWithCustomInputStringAttribute[0].GetParameters()[0].ParameterType.FullName);
+ }
+ break;
+ default:
+ throw new DuplicateObjectException(methodsWithCustomInputStringAttribute[1].Name, new List { "[CustomInputString] attribute" }, methodsWithCustomInputStringAttribute[0].Name, "Error in class " + property.PropertyType.Name + ". It is expected that only one method may have the [CustomInputString] attribute, but there are " + methodsWithCustomInputStringAttribute.Count + " methods with this attribute");
+ }
+
+ return argumentDescriptor;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ if (string.IsNullOrEmpty(property.GetCustomAttribute()!.StringFormat))
+ {
+ /*
+ * CustomInputStringAttribute without arguments is redundant and should not be used.
+ * However it may happen that it is used by mistake or for some incomprehension,
+ * so consider this case
+ */
+ argumentDescriptor = SetArgumentValueIfTypeDoesNotExist(parentObject, property, argumentDescriptor, userValueDescriptor);
+ }
+ else
+ {
+ try
+ {
+ // Use ParseExact method
+ argumentDescriptor.Value = argumentDescriptor.ParameterType.GetMethod("ParseExact", new[] { typeof(string), typeof(string), typeof(IFormatProvider) })!.Invoke(null, new[] { userValueDescriptor.Value, property.GetCustomAttribute()!.StringFormat, CultureInfo.InvariantCulture })!;
+ property.SetValue(parentObject, argumentDescriptor.Value);
+ argumentDescriptor.IsSetByUser = true;
+ }
+ catch (Exception exc)
+ {
+ throw new ArgumentException("The value provided to argument " + userValueDescriptor.Name + " is not acceptable. Reason: " + exc.GetBaseException().Message, userValueDescriptor.Name, exc.InnerException);
+ }
+ }
+ return argumentDescriptor;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ return argumentDescriptor;
+ }
+ }
+}
diff --git a/src/InterAppConnector/Rules/DefaultRule.cs b/src/InterAppConnector/Rules/DefaultRule.cs
new file mode 100644
index 0000000..22908e9
--- /dev/null
+++ b/src/InterAppConnector/Rules/DefaultRule.cs
@@ -0,0 +1,169 @@
+using InterAppConnector.Attributes;
+using InterAppConnector.DataModels;
+using InterAppConnector.Interfaces;
+using System.Reflection;
+
+namespace InterAppConnector.Rules
+{
+ public class DefaultRule : IArgumentDefinitionRule, IArgumentSettingRule
+ {
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor descriptor)
+ {
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ descriptor.OriginalPropertyName = property.Name;
+
+ Type? parameterType = Nullable.GetUnderlyingType(property.PropertyType);
+
+ if (parameterType == null)
+ {
+ descriptor.ParameterType = property.PropertyType;
+ }
+ else
+ {
+ descriptor.ParameterType = parameterType;
+ }
+
+ descriptor.Attributes = property.GetCustomAttributes().ToList();
+ descriptor.Value = property.GetValue(parentObject)!;
+
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, FieldInfo field, ParameterDescriptor descriptor)
+ {
+ descriptor.OriginalPropertyName = field.Name;
+ descriptor.Value = (int) field.GetValue(parentObject)!;
+ return descriptor;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(PropertyInfo property)
+ {
+ bool isRuleEnabled = true;
+
+ if (property.GetCustomAttribute() != null)
+ {
+ isRuleEnabled = false;
+ }
+
+ return isRuleEnabled;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(FieldInfo field)
+ {
+ bool isRuleEnabled = true;
+
+ if (field.GetCustomAttribute() != null)
+ {
+ isRuleEnabled = false;
+ }
+
+ return isRuleEnabled;
+ }
+
+ public bool IsRuleEnabledInArgumentSetting(PropertyInfo property)
+ {
+ Type? parameterType = Nullable.GetUnderlyingType(property.PropertyType);
+ if (parameterType == null)
+ {
+ parameterType = property.PropertyType;
+ }
+ bool isEnumType = parameterType.IsEnum;
+ bool isValueTypeAndIsNotAStruct = parameterType.IsValueType && !StructHelper.IsStruct(parameterType);
+ return isEnumType || isValueTypeAndIsNotAStruct;
+ }
+
+ public bool IsRuleEnabledInArgumentSetting(FieldInfo field)
+ {
+ return false;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ return argumentDescriptor;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ return argumentDescriptor;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ if (argumentDescriptor.ParameterType.IsEnum)
+ {
+ /*
+ * Remember that a value in an enumeration may have different aliases that works
+ * like aliases in properties, with the main difference that refers to a value instead of
+ * the property.
+ * Aliases can indentify a value uniquely and could mask the original value name, but be careful for batch execution, where the value
+ * passed to the property is also the name of the property
+ */
+ try
+ {
+ argumentDescriptor.Value = EnumHelper.GetEnumerationFieldByValue(argumentDescriptor.ParameterType, userValueDescriptor.Value.ToString()!);
+ property.SetValue(parentObject, EnumHelper.GetEnumerationFieldByValue(argumentDescriptor.ParameterType, userValueDescriptor.Value.ToString()!));
+ argumentDescriptor.IsSetByUser = true;
+ }
+ catch (ArgumentException exc)
+ {
+ /*
+ * If something went wrong with the parse of the value, throw an exception.
+ * You may need to change this exception with a more specialized exception,
+ * but the InnerException property should contain the exception raised by
+ * EnumHelper.GetFieldName()
+ */
+ throw new ArgumentException("The value provided in parameter " + userValueDescriptor.Name + " is not acceptable. Please provide a new value", userValueDescriptor.Name, exc);
+ }
+ }
+ else
+ {
+ try
+ {
+ /*
+ * During the parse of the arguments, if an argument is passed without a value is considered a switch
+ * This is not always true, especially if the argument is placed as last token in the argument definition
+ * So if the type of the argument is not a boolean, you have to specify a value explicitly
+ */
+ if (argumentDescriptor.ParameterType != typeof(bool) && !(userValueDescriptor.Value is bool))
+ {
+ argumentDescriptor.Value = Convert.ChangeType(userValueDescriptor.Value, argumentDescriptor.ParameterType);
+ property.SetValue(parentObject, Convert.ChangeType(userValueDescriptor.Value, argumentDescriptor.ParameterType));
+ argumentDescriptor.IsSetByUser = true;
+ }
+ else
+ {
+ if (argumentDescriptor.ParameterType == typeof(bool))
+ {
+ argumentDescriptor.Value = Convert.ChangeType(userValueDescriptor.Value, argumentDescriptor.ParameterType);
+ property.SetValue(parentObject, Convert.ChangeType(userValueDescriptor.Value, argumentDescriptor.ParameterType));
+ argumentDescriptor.IsSetByUser = true;
+ }
+ else
+ {
+ throw new ArgumentException("The value provided to argument " + userValueDescriptor.Name + " is not acceptable. Please provide a valid value", userValueDescriptor.Name);
+ }
+ }
+ }
+ catch (Exception exc)
+ {
+ throw new ArgumentException("The value provided to argument " + userValueDescriptor.Name + " is not acceptable. Please provide a valid value", userValueDescriptor.Name, exc);
+ }
+ }
+ return argumentDescriptor;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ return argumentDescriptor;
+ }
+ }
+}
diff --git a/src/InterAppConnector/Rules/DescriptionRule.cs b/src/InterAppConnector/Rules/DescriptionRule.cs
new file mode 100644
index 0000000..8da381f
--- /dev/null
+++ b/src/InterAppConnector/Rules/DescriptionRule.cs
@@ -0,0 +1,71 @@
+using InterAppConnector.Attributes;
+using InterAppConnector.DataModels;
+using InterAppConnector.Interfaces;
+using System.ComponentModel;
+using System.Reflection;
+
+namespace InterAppConnector.Rules
+{
+ public class DescriptionRule : IArgumentDefinitionRule
+ {
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ descriptor.Description = "No description provided";
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor descriptor)
+ {
+ descriptor.Description = "No description provided";
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ DescriptionAttribute? attribute = property.GetCustomAttribute();
+
+ if (attribute != null)
+ {
+ descriptor.Description = attribute.Description;
+ }
+
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, FieldInfo field, ParameterDescriptor descriptor)
+ {
+ DescriptionAttribute? attribute = field.GetCustomAttribute();
+
+ if (attribute != null)
+ {
+ descriptor.Description = attribute.Description;
+ }
+
+ return descriptor;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(PropertyInfo property)
+ {
+ bool isRuleEnabled = true;
+
+ if (property.GetCustomAttribute() != null)
+ {
+ isRuleEnabled = false;
+ }
+
+ return isRuleEnabled;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(FieldInfo field)
+ {
+ bool isRuleEnabled = true;
+
+ if (field.GetCustomAttribute() != null)
+ {
+ isRuleEnabled = false;
+ }
+
+ return isRuleEnabled;
+ }
+ }
+}
diff --git a/src/InterAppConnector/Rules/ExampleValueRule.cs b/src/InterAppConnector/Rules/ExampleValueRule.cs
new file mode 100644
index 0000000..421b071
--- /dev/null
+++ b/src/InterAppConnector/Rules/ExampleValueRule.cs
@@ -0,0 +1,45 @@
+using InterAppConnector.Attributes;
+using InterAppConnector.DataModels;
+using InterAppConnector.Interfaces;
+using System.Reflection;
+
+namespace InterAppConnector.Rules
+{
+ public class ExampleValueRule : IArgumentDefinitionRule
+ {
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor descriptor)
+ {
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ ExampleValueAttribute? attribute = property.GetCustomAttribute();
+ if (string.IsNullOrEmpty(attribute!.ExampleValue))
+ {
+ throw new ArgumentException("The example value cannot be null or empty", property.Name);
+ }
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, FieldInfo field, ParameterDescriptor descriptor)
+ {
+ return descriptor;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(PropertyInfo property)
+ {
+ return true;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(FieldInfo field)
+ {
+ return false;
+ }
+ }
+}
diff --git a/src/InterAppConnector/Rules/MandatoryForCommandRule.cs b/src/InterAppConnector/Rules/MandatoryForCommandRule.cs
new file mode 100644
index 0000000..e7d5aa7
--- /dev/null
+++ b/src/InterAppConnector/Rules/MandatoryForCommandRule.cs
@@ -0,0 +1,76 @@
+using InterAppConnector.Attributes;
+using InterAppConnector.DataModels;
+using InterAppConnector.Interfaces;
+using System.Reflection;
+
+namespace InterAppConnector.Rules
+{
+ public class MandatoryForCommandRule : IArgumentDefinitionRule
+ {
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ if (property.PropertyType.IsValueType)
+ {
+ if (Nullable.GetUnderlyingType(property.PropertyType) == null)
+ {
+ descriptor.IsMandatory = true;
+ }
+ }
+ else
+ {
+ if (property.GetValue(parentObject) != null)
+ {
+ property.SetValue(parentObject, null);
+ descriptor.IsMandatory = true;
+ }
+ }
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor descriptor)
+ {
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ foreach (MandatoryForCommandAttribute propertyAttribute in property.GetCustomAttributes())
+ {
+ if (propertyAttribute.Command == CommandManager.CurrentCommand!.GetType())
+ {
+ descriptor.IsMandatory = true;
+ }
+ }
+ return descriptor;
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, FieldInfo field, ParameterDescriptor descriptor)
+ {
+ return descriptor;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(PropertyInfo property)
+ {
+ bool isRuleEnabled = true;
+
+ if (property.GetCustomAttribute() != null)
+ {
+ isRuleEnabled = false;
+ }
+
+ return isRuleEnabled;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(FieldInfo field)
+ {
+ bool isRuleEnabled = true;
+
+ if (field.GetCustomAttribute() != null)
+ {
+ isRuleEnabled = false;
+ }
+
+ return isRuleEnabled;
+ }
+ }
+}
diff --git a/src/InterAppConnector/Rules/ValueValidatorRule.cs b/src/InterAppConnector/Rules/ValueValidatorRule.cs
new file mode 100644
index 0000000..8312977
--- /dev/null
+++ b/src/InterAppConnector/Rules/ValueValidatorRule.cs
@@ -0,0 +1,70 @@
+using InterAppConnector.Attributes;
+using InterAppConnector.DataModels;
+using InterAppConnector.Exceptions;
+using InterAppConnector.Interfaces;
+using System.Reflection;
+
+namespace InterAppConnector.Rules
+{
+ public class ValueValidatorRule : IArgumentSettingRule
+ {
+ public bool IsRuleEnabledInArgumentSetting(PropertyInfo property)
+ {
+ return true;
+ }
+
+ public bool IsRuleEnabledInArgumentSetting(FieldInfo field)
+ {
+ return true;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ return argumentDescriptor;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ return argumentDescriptor;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ ValueValidatorAttribute validator = property.GetCustomAttribute()!;
+
+ if (validator.ValueValidatorType.GetInterface(typeof(IValueValidator).Name) != null)
+ {
+ IValueValidator valueValidator = (IValueValidator)Activator.CreateInstance(validator.ValueValidatorType)!;
+ bool customValidationErrorMessageMissing = false;
+
+ try
+ {
+ if (!valueValidator.ValidateValue(argumentDescriptor.Value))
+ {
+ customValidationErrorMessageMissing = true;
+ }
+ }
+ catch (Exception exc)
+ {
+ throw new ArgumentException("The value provided to argument " + userValueDescriptor.Name + " is not acceptable. Reason: " + exc.GetBaseException().Message, userValueDescriptor.Name, exc.InnerException);
+ }
+
+ if (customValidationErrorMessageMissing)
+ {
+ throw new ArgumentException("The value provided to argument " + userValueDescriptor.Name + " is not valid according to the validation procedure");
+ }
+ }
+ else
+ {
+ throw new TypeMismatchException(typeof(IValueValidator).Name, "", "", validator.ValueValidatorType.Name + " doesn't have an interface of type " + typeof(IValueValidator).Name);
+ }
+
+ return argumentDescriptor;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ return argumentDescriptor;
+ }
+ }
+}
diff --git a/tests/InterAppConnector.Test.Library/CommandManagerTest.cs b/tests/InterAppConnector.Test.Library/CommandManagerTest.cs
index 84dc38d..fda09f3 100644
--- a/tests/InterAppConnector.Test.Library/CommandManagerTest.cs
+++ b/tests/InterAppConnector.Test.Library/CommandManagerTest.cs
@@ -114,17 +114,17 @@ public void AddCommand_AddExampleCommands_ShouldConfigureObjectProperly()
.AddCommand()
.AddCommand();
- Assert.That(command._commands.Count, Is.EqualTo(4));
+ Assert.That(command._commands, Has.Count.EqualTo(4));
Assert.That(command._commands[typeof(AppendTextCommand).FullName].GetType(), Is.EqualTo(typeof(AppendTextCommand)));
Assert.That(command._commands[typeof(CreateFileCommand).FullName].GetType(), Is.EqualTo(typeof(CreateFileCommand)));
Assert.That(command._commands[typeof(WriteTextCommand).FullName].GetType(), Is.EqualTo(typeof(WriteTextCommand)));
Assert.That(command._commands[typeof(ReadFileCommand).FullName].GetType(), Is.EqualTo(typeof(ReadFileCommand)));
- Assert.That(command._arguments.Count, Is.EqualTo(4));
- Assert.That(command._arguments[typeof(AppendTextCommand).FullName].Arguments.Count, Is.EqualTo(3));
- Assert.That(command._arguments[typeof(CreateFileCommand).FullName].Arguments.Count, Is.EqualTo(3));
- Assert.That(command._arguments[typeof(WriteTextCommand).FullName].Arguments.Count, Is.EqualTo(3));
- Assert.That(command._arguments[typeof(ReadFileCommand).FullName].Arguments.Count, Is.EqualTo(2));
- Assert.That(command._parameterObject.Count, Is.EqualTo(4));
+ Assert.That(command._arguments, Has.Count.EqualTo(4));
+ Assert.That(command._arguments[typeof(AppendTextCommand).FullName].Arguments, Has.Count.EqualTo(3));
+ Assert.That(command._arguments[typeof(CreateFileCommand).FullName].Arguments, Has.Count.EqualTo(3));
+ Assert.That(command._arguments[typeof(WriteTextCommand).FullName].Arguments, Has.Count.EqualTo(3));
+ Assert.That(command._arguments[typeof(ReadFileCommand).FullName].Arguments, Has.Count.EqualTo(2));
+ Assert.That(command._parameterObject, Has.Count.EqualTo(4));
Assert.That(command._parameterObject[typeof(AppendTextCommand).FullName].GetType(), Is.EqualTo(typeof(FileManagerParameter)));
Assert.That(command._parameterObject[typeof(CreateFileCommand).FullName].GetType(), Is.EqualTo(typeof(FileManagerParameter)));
Assert.That(command._parameterObject[typeof(WriteTextCommand).FullName].GetType(), Is.EqualTo(typeof(FileManagerParameter)));
@@ -138,7 +138,7 @@ public void AddCommand_CheckMandatoryParameters_ShouldConfigureObjectProperly()
command.AddCommand();
- Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments.Count, Is.EqualTo(9));
+ Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments, Has.Count.EqualTo(9));
Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments["mandatorynumber"].IsMandatory, Is.EqualTo(true));
Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments["mandatoryfileinfo"].IsMandatory, Is.EqualTo(true));
Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments["mandatoryguid"].IsMandatory, Is.EqualTo(true));
@@ -152,7 +152,7 @@ public void AddCommand_CheckOptionalParameters_ShouldConfigureObjectProperly()
command.AddCommand();
- Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments.Count, Is.EqualTo(9));
+ Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments, Has.Count.EqualTo(9));
Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments["number"].IsMandatory, Is.EqualTo(false));
Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments["guid"].IsMandatory, Is.EqualTo(false));
Assert.That(command._arguments[typeof(MultipleArgumentTypeCommand).FullName].Arguments["switch"].IsMandatory, Is.EqualTo(false));
@@ -300,7 +300,7 @@ public void SetArgument_WithValidatorCustomInputStringAndValueInRange_ReturnArgu
}
[TestCase("validatedcustomclass")]
- //[TestCase("othervalidatedcustomclass")]
+ [TestCase("othervalidatedcustomclass")]
public void SetArgument_WithAnotherValidatorCustomInputStringAndValueInRange_ReturnArgumentSet(string argument)
{
Argument arguments = Argument.Parse(new[] { "setargument", "-" + argument, "apple,pear" }, "-");
@@ -309,7 +309,7 @@ public void SetArgument_WithAnotherValidatorCustomInputStringAndValueInRange_Ret
manager.SetArguments(new List(new[] { "setargument" }), arguments.Arguments.Values.ToList());
- Assert.That(((CustomStringFormatClass)manager._arguments[typeof(SetArgumentCommand).FullName].Arguments[argument].Value).List.Count, Is.EqualTo(2));
+ Assert.That(((CustomStringFormatClass)manager._arguments[typeof(SetArgumentCommand).FullName].Arguments[argument].Value).List, Has.Count.EqualTo(2));
}
[Test]
@@ -359,7 +359,7 @@ public void SetArgument_WithValidatorCustomInputStringAndValueNotInRange_ReturnA
}
[TestCase("validatedcustomclass")]
- //[TestCase("othervalidatedcustomclass")]
+ [TestCase("othervalidatedcustomclass")]
public void SetArgument_WithAnotherValidatorCustomInputStringAndValueNotInRange_ReturnArgumentException(string argument)
{
Argument arguments = Argument.Parse(new[] { "setargument", "-" + argument, "apple,grapefruitpear" }, "-");
@@ -376,6 +376,9 @@ public void SetArgument_WithAnotherValidatorCustomInputStringAndValueNotInRange_
[TestCase("abcd123a")]
[TestCase("ab")]
+ //
+ [TestCase("")]
+ //
public void SetArgument_ParameterWithWrongCustomString_ReturnArgumentException(string value)
{
Argument arguments = Argument.Parse(new[] { "setargument", "-plate", value }, "-");
diff --git a/tests/InterAppConnector.Test.Library/DataModels/SetArgumentMethodDataModel.cs b/tests/InterAppConnector.Test.Library/DataModels/SetArgumentMethodDataModel.cs
index 0853640..fd28aa5 100644
--- a/tests/InterAppConnector.Test.Library/DataModels/SetArgumentMethodDataModel.cs
+++ b/tests/InterAppConnector.Test.Library/DataModels/SetArgumentMethodDataModel.cs
@@ -81,12 +81,9 @@ public class SetArgumentMethodDataModel
[ValueValidator(typeof(AgeValidatorWithCustomErrorMessageValidator))]
public uint ValidatedValue { get; set; }
-
- /*
- * To check. There may be a bug here
- * [ValueValidator(typeof(CustomStringClassvalidator))]
+
+ [ValueValidator(typeof(CustomStringClassValidator))]
[CustomInputString]
public CustomStringFormatClass OtherValidatedCustomClass { get; set; }
- */
}
}
diff --git a/tests/InterAppConnector.Test.Library/Enumerations/VehicleType.cs b/tests/InterAppConnector.Test.Library/Enumerations/VehicleType.cs
index 986cd75..1c5e8d0 100644
--- a/tests/InterAppConnector.Test.Library/Enumerations/VehicleType.cs
+++ b/tests/InterAppConnector.Test.Library/Enumerations/VehicleType.cs
@@ -19,7 +19,7 @@ public enum VehicleType
Airplane = 20,
- [ExcludeItemFromCommandAttribute]
+ [ExcludeItemFromCommand]
Undefined = 25
}
}
diff --git a/tests/InterAppConnector.Test.Library/Rules/CustomInputStringRuleTest.cs b/tests/InterAppConnector.Test.Library/Rules/CustomInputStringRuleTest.cs
new file mode 100644
index 0000000..76b6b3c
--- /dev/null
+++ b/tests/InterAppConnector.Test.Library/Rules/CustomInputStringRuleTest.cs
@@ -0,0 +1,46 @@
+using InterAppConnector.DataModels;
+using InterAppConnector.Rules;
+using NUnit.Framework;
+
+namespace InterAppConnector.Test.Library.Rules
+{
+ ///
+ /// These tests are used only to increase the code coverage score.
+ /// The methods thested in this class will not be used in real applications
+ ///
+ public class CustomInputStringRuleTest
+ {
+ public static int fictiousField;
+ public static int FictiousProperty { get; set; }
+
+ [Theory]
+ public void IsRuleEnabledInArgumentSetting_WithAFictiousField_ReturnTrue()
+ {
+ CustomInputStringRule rule = new CustomInputStringRule();
+
+ bool returnFalse = rule.IsRuleEnabledInArgumentSetting(typeof(CustomInputStringRuleTest).GetFields()[0]);
+
+ Assert.That(returnFalse, Is.False);
+ }
+
+ [Theory]
+ public void SetArgumentValueIfTypeDoesNotExist_WithAFictiousField_ReturnNotImplementedException()
+ {
+ CustomInputStringRule rule = new CustomInputStringRule();
+
+ ParameterDescriptor descriptor = rule.SetArgumentValueIfTypeDoesNotExist(null, typeof(CustomInputStringRuleTest).GetFields()[0], new ParameterDescriptor(), new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+
+ [Theory]
+ public void SetArgumentValueIfTypeExists_WithAFictiousField_ReturnNotImplementedException()
+ {
+ CustomInputStringRule rule = new CustomInputStringRule();
+
+ ParameterDescriptor descriptor = rule.SetArgumentValueIfTypeExists(null, typeof(CustomInputStringRuleTest).GetFields()[0], new ParameterDescriptor(), new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+ }
+}
diff --git a/tests/InterAppConnector.Test.Library/Rules/DefaultRuleTest.cs b/tests/InterAppConnector.Test.Library/Rules/DefaultRuleTest.cs
new file mode 100644
index 0000000..663c3d4
--- /dev/null
+++ b/tests/InterAppConnector.Test.Library/Rules/DefaultRuleTest.cs
@@ -0,0 +1,76 @@
+using InterAppConnector.DataModels;
+using InterAppConnector.Rules;
+using NUnit.Framework;
+
+namespace InterAppConnector.Test.Library.Rules
+{
+ ///
+ /// These tests are used only to increase the code coverage score.
+ /// The methods thested in this class will not be used in real applications
+ ///
+ public class DefaultRuleTest
+ {
+ public static int fictiousField;
+ public static int FictiousProperty { get; set; }
+
+ [Theory]
+ public void SetArgumentValueIfTypeDoesNotExist_WithAFictiousField_ReturnArgumentDescriptor()
+ {
+ DefaultRule rule = new DefaultRule();
+
+ ParameterDescriptor descriptor = rule.SetArgumentValueIfTypeDoesNotExist(null, typeof(DefaultRuleTest).GetFields()[0], new ParameterDescriptor(), new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+
+ [Theory]
+ public void SetArgumentValueIfTypeDoesNotExist_WithAFictiousProperty_ReturnArgumentDescriptor()
+ {
+ DefaultRule rule = new DefaultRule();
+
+ ParameterDescriptor descriptor = rule.SetArgumentValueIfTypeDoesNotExist(null, typeof(DefaultRuleTest).GetProperties()[0], new ParameterDescriptor(), new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+
+ [Theory]
+ public void DefineArgumentIfTypeDoesNotExist_WithAFictiousField_ReturnArgumentDescriptor()
+ {
+ DefaultRule rule = new DefaultRule();
+
+ ParameterDescriptor descriptor = rule.DefineArgumentIfTypeDoesNotExist(null, typeof(DefaultRuleTest).GetFields()[0], new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+
+ [Theory]
+ public void DefineArgumentIfTypeDoesNotExist_WithAFictiousProperty_ReturnArgumentDescriptor()
+ {
+ DefaultRule rule = new DefaultRule();
+
+ ParameterDescriptor descriptor = rule.DefineArgumentIfTypeDoesNotExist(null, typeof(DefaultRuleTest).GetProperties()[0], new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+
+ [Theory]
+ public void IsRuleEnabledInArgumentSetting_WithAFictiousField_ReturnFalse()
+ {
+ DefaultRule rule = new DefaultRule();
+
+ bool returnFalse = rule.IsRuleEnabledInArgumentSetting(typeof(DefaultRuleTest).GetFields()[0]);
+
+ Assert.That(returnFalse, Is.False);
+ }
+
+ [Theory]
+ public void SetArgumentValueIfTypeExists_WithAFictiousField_ReturnArgumentDescriptor()
+ {
+ DefaultRule rule = new DefaultRule();
+
+ ParameterDescriptor descriptor = rule.SetArgumentValueIfTypeExists(null, typeof(DefaultRuleTest).GetFields()[0], new ParameterDescriptor(), new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+ }
+}
diff --git a/tests/InterAppConnector.Test.Library/Rules/ExampleValueRuleTest.cs b/tests/InterAppConnector.Test.Library/Rules/ExampleValueRuleTest.cs
new file mode 100644
index 0000000..a0c8606
--- /dev/null
+++ b/tests/InterAppConnector.Test.Library/Rules/ExampleValueRuleTest.cs
@@ -0,0 +1,36 @@
+using InterAppConnector.DataModels;
+using InterAppConnector.Rules;
+using NUnit.Framework;
+
+namespace InterAppConnector.Test.Library.Rules
+{
+ ///
+ /// These tests are used only to increase the code coverage score.
+ /// The methods thested in this class will not be used in real applications
+ ///
+ public class ExampleValueRuleTest
+ {
+ public static int fictiousField;
+ public static int FictiousProperty { get; set; }
+
+ [Theory]
+ public void DefineArgumentIfTypeExists_WithAFictiousField_ReturnNotImplementedException()
+ {
+ ExampleValueRule rule = new ExampleValueRule();
+
+ ParameterDescriptor descriptor = rule.DefineArgumentIfTypeExists(null, typeof(ExampleValueRuleTest).GetFields()[0], new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+
+ [Theory]
+ public void DefineArgumentIfTypeDoesNotExist_WithAFictiousField_ReturnNotImplementedException()
+ {
+ ExampleValueRule rule = new ExampleValueRule();
+
+ ParameterDescriptor descriptor = rule.DefineArgumentIfTypeDoesNotExist(null, typeof(ExampleValueRuleTest).GetFields()[0], new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+ }
+}
diff --git a/tests/InterAppConnector.Test.Library/Rules/GenericRuleTest.cs b/tests/InterAppConnector.Test.Library/Rules/GenericRuleTest.cs
new file mode 100644
index 0000000..b90f0ed
--- /dev/null
+++ b/tests/InterAppConnector.Test.Library/Rules/GenericRuleTest.cs
@@ -0,0 +1,90 @@
+using InterAppConnector.DataModels;
+using InterAppConnector.Interfaces;
+using NUnit.Framework;
+using System.Reflection;
+
+namespace InterAppConnector.Test.Library.Rules
+{
+ internal class GenericRuleTest : IArgumentDefinitionRule, IArgumentSettingRule
+ {
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor descriptor)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, FieldInfo field, ParameterDescriptor descriptor)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(PropertyInfo property)
+ {
+ return false;
+ }
+
+ public bool IsRuleEnabledInArgumentDefinition(FieldInfo field)
+ {
+ return false;
+ }
+
+ public bool IsRuleEnabledInArgumentSetting(PropertyInfo property)
+ {
+ return false;
+ }
+
+ public bool IsRuleEnabledInArgumentSetting(FieldInfo field)
+ {
+ return false;
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeDoesNotExist(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ParameterDescriptor SetArgumentValueIfTypeExists(object parentObject, FieldInfo property, ParameterDescriptor argumentDescriptor, ParameterDescriptor userValueDescriptor)
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ public void TestDefineRule_ShouldReturnTrue()
+ {
+ GenericRuleTest test = new GenericRuleTest();
+
+ bool returnTrue = ((IArgumentDefinitionRule)test).ReturnTrue(23);
+
+ Assert.That(returnTrue, Is.True);
+ }
+
+ [Theory]
+ public void TestSetRule_ShouldReturnTrue()
+ {
+ GenericRuleTest test = new GenericRuleTest();
+
+ bool returnTrue = ((IArgumentSettingRule)test).ReturnTrue(23);
+
+ Assert.That(returnTrue, Is.True);
+ }
+ }
+}
diff --git a/tests/InterAppConnector.Test.Library/Rules/MandatoryForCommandRuleTest.cs b/tests/InterAppConnector.Test.Library/Rules/MandatoryForCommandRuleTest.cs
new file mode 100644
index 0000000..57891d1
--- /dev/null
+++ b/tests/InterAppConnector.Test.Library/Rules/MandatoryForCommandRuleTest.cs
@@ -0,0 +1,23 @@
+using InterAppConnector.DataModels;
+using InterAppConnector.Rules;
+using NUnit.Framework;
+
+namespace InterAppConnector.Test.Library.Rules
+{
+ ///
+ /// These tests are used only to increase the code coverage score.
+ /// The methods thested in this class will not be used in real applications
+ ///
+ public class MandatoryForCommandRuleTest
+ {
+ [Theory]
+ public void DefineArgumentIfTypeExists_WithAFictiousField_ReturnArgumentDescriptor()
+ {
+ MandatoryForCommandRule rule = new MandatoryForCommandRule();
+
+ ParameterDescriptor descriptor = rule.DefineArgumentIfTypeExists(null, typeof(ExampleValueRuleTest).GetFields()[0], new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+ }
+}
diff --git a/tests/InterAppConnector.Test.Library/Rules/ValueValidatorRuleTest.cs b/tests/InterAppConnector.Test.Library/Rules/ValueValidatorRuleTest.cs
new file mode 100644
index 0000000..e7750b4
--- /dev/null
+++ b/tests/InterAppConnector.Test.Library/Rules/ValueValidatorRuleTest.cs
@@ -0,0 +1,42 @@
+using InterAppConnector.DataModels;
+using InterAppConnector.Rules;
+using NUnit.Framework;
+
+namespace InterAppConnector.Test.Library.Rules
+{
+ public class ValueValidatorRuleTest
+ {
+ public static int fictiousField;
+ public static int FictiousProperty { get; set; }
+
+ [Theory]
+ public void IsRuleEnabledInArgumentSetting_WithAFictiousField_ReturnTrue()
+ {
+ ValueValidatorRule rule = new ValueValidatorRule();
+
+ bool returnFalse = rule.IsRuleEnabledInArgumentSetting(typeof(ValueValidatorRuleTest).GetFields()[0]);
+
+ Assert.That(returnFalse, Is.True);
+ }
+
+ [Theory]
+ public void SetArgumentValueIfTypeDoesNotExist_WithAFictiousField_ReturnArgumentDescriptor()
+ {
+ ValueValidatorRule rule = new ValueValidatorRule();
+
+ ParameterDescriptor descriptor = rule.SetArgumentValueIfTypeDoesNotExist(null, typeof(ValueValidatorRuleTest).GetFields()[0], new ParameterDescriptor(), new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+
+ [Theory]
+ public void SetArgumentValueIfTypeExists_WithAFictiousField_ReturnArgumentDescriptor()
+ {
+ ValueValidatorRule rule = new ValueValidatorRule();
+
+ ParameterDescriptor descriptor = rule.SetArgumentValueIfTypeExists(null, typeof(ValueValidatorRuleTest).GetFields()[0], new ParameterDescriptor(), new ParameterDescriptor());
+
+ Assert.That(descriptor, Is.EqualTo(new ParameterDescriptor()));
+ }
+ }
+}