-
Notifications
You must be signed in to change notification settings - Fork 0
Argument definition rules
From version 0.4.0, you can define definition rules. In this page you will find information about argument definition rules. In particular, it contains:
- what is a definition rule
- generic definition rule
- definition rule specific to an attribute
- an example that shows how to use a definition rule
Prior to read this page, it is suggested to read the page that explains what is a rule in general
Argument definition rules are rules that are executed when the argument is created and defined. For this reason, they are the first rules evaluated by the library. At this point, the value inserted by the user is not known.
For each of the argument created, the library creates a ParameterDescriptor object that contains the informations about the argument (name, aliases, type, ...).
You can create two types of argument rules:
- generic rules
- specializeed rules
Generic rules are not associated to any attribute, and they are very useful if you want to define a generic rule for an object. You may need to define an argument that does not have any specific attribute, but you have to associate some specific tasks or add some functionalities. Generic rules helps to cover this case.
In order to define a generic rule, you have to use a class that implements the IArgumentDefinitionRule interface, as showed in the code below
public class GenericRule : 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, FieldInfo field, ParameterDescriptor descriptor)
{
return descriptor;
}
public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
{
return descriptor;
}
public bool IsRuleEnabledInArgumentDefinition(PropertyInfo property)
{
return true;
}
public bool IsRuleEnabledInArgumentDefinition(FieldInfo field)
{
return true;
}
}In particular, you can see that there are three main methods that have two overloads (for a total of six methods)
-
IsRuleEnabledInArgumentDefinitionis executed always and define if the rule should be executed or not -
DefineArgumentIfTypeDoesNotExistis not executed in any case in generic rules. Probably they wll be removed in future versions -
DefineArgumentIfTypeExistsis executed if the rule is enabled
The main difference between the overloads is that one method accept a property (the method with PropertyInfo) and the other accept a field (the method with FieldInfo)
Specialized rules are associated to an attribute, and they are very useful if you want to define a behaviour for a rule that has a specific attribute.
Let's assume you have created an attribute called MyCustomAttribute and you want to define a rule.
In order to define a specific rule, you have to use a class that implements the IArgumentDefinitionRule<ParameterType> interface, as showed in the code below
public class GenericRule : IArgumentDefinitionRule<MyCustomAttributeAttribute>
{
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, FieldInfo field, ParameterDescriptor descriptor)
{
return descriptor;
}
public ParameterDescriptor DefineArgumentIfTypeExists(object parentObject, PropertyInfo property, ParameterDescriptor descriptor)
{
return descriptor;
}
public bool IsRuleEnabledInArgumentDefinition(PropertyInfo property)
{
return true;
}
public bool IsRuleEnabledInArgumentDefinition(FieldInfo field)
{
return true;
}
}In particular, you can see that there are three main methods that have two overloads (for a total of six methods)
-
IsRuleEnabledInArgumentDefinitionis executed always and define if the rule should be executed or not -
DefineArgumentIfTypeExistsis executed if the type or the attrbute exists and the rule is enabled -
DefineArgumentIfTypeDoesNotExistis executed only if the attribute or the type is not present and if the rule is enabled
The main difference between the overloads is that one method accept a property (the method with PropertyInfo) and the other accept a field (the method with FieldInfo)
In this example, we will create a simple hello world definition rule that will print a message when an argument of a custom type is defined as argument of a command
We will create
- the library that contains the rule and an example command
- the console application
For this example it is assumed that you have learned what is a command and how to implement it
Follow these steps to complete this example:
- Clone the example repository available here
- Build and run the BasicArgumentDefinitionRule project available in folder rule
- If you try to execute the
activityexamplecommand, you can see something like the output below:
[04/01/2024 18:49:11] SUCCESS (0) : 2 elements in the list
Executing generic definition rule contained in the library
Command start- Getting started
- Create Commands
- Manage arguments
- Argument basics
- Shared arguments between different commands
- Argument aliases
- Argument description
- Exclude an argument from argument list
- Use enumerations as argument
- Use objects and structs as argument type
- Validate argument value before command execution
- Customize the command example in command help
- Define rules