Advanced programming
In the code sample of the chapter "Starting an ACComponent" the method "ACUrlCommand" was used to query the existence of an instance. The ACUrlCommand is a universal method that can be used to query the existence of an instance via a string (ACUrl) to:
In order to distinguish which of the previously listed functions (a-e) has to be executed via an ACUrlCommand, special command characters must be inserted in the ACUrl string - similar to the URL parameters for http or REST.
This method has the following signature:
object ACUrlCommand(string acUrl, params Object[] acParameter)
In the first parameter, the command string (ACUrl) is passed. To call a method that has several parameters, enter the parameters in the following argument list. You can read more about this in the chapter "Synchronous Methods".
The following example code refers to a graphical example of an application tree from the parent chapter. grafische Beispiel eines Anwendungsbaumes aus dem übergeordneten Kapitel. It contains examples for the command types a and d.
ACUrl string command characters:
Character | Description |
---|---|
\ | Path separator. If the separator is set to the beginning, this means the beginning of an absolute addressing. Then an Identifier must follow. Example: \Mixery\Scale1 |
.\ | Relative addressierung: An object is adressed which is located in the directory (child) below. Then an Identifier must follow. Example: .\Flap1 |
..\ | Relative addressing: An object is located in the parent directory. Then an Identifier can follow. Example: ..\ or ..\Mixer1 |
? | Check for the existence of an ACComponent instance. The question mark always has to be at the beginning of the character string! It is followd by the Url. Example: ?.\Flap1 or ?\Mixery\Scale1 |
# | Start a new ACComponent instance (force an instance). Then an Identifier must follow. Example: #Flap1 or .\#Flap1 or absolute \Mixery\Scale1\#Flap1 |
~ | Stopping an ACComponent instance. Then an Identifier must follow. Example: ~Flap1 or .\~Flap1 or absolute \Mixery\Scale1\~Flap1 |
! | Call a method. This must be followed by a Method Name (Identifier). Example: !Open or .\Flap1!Open or absolute \Mixery\Scale1\Flap1!Open |
§ | Access to a translated text. Then an Identifier of the translation text must follow. Example: §Warning50001 or .\Flap1§Warning50001 or absolute \Mixery\Scale1\Flap1§Warning50001 |
^ | Sending a custom message/command. |
In the User Management it can be defined which application should be started under which user account. If the server flag is set for the assigned application, then the instances defined in the application tree are instantiated as real .NET classes ("Real"-Components) when the application is started. If, on the other hand, the client flag is set, "proxy" instances are created instead. All property accesses and method calls to such instances take place in the background. This means that these accesses are delegated via network to another iPlus instance, where these instances exist as real classes. (Sources for the proxy design pattern and the principle functionality:
So if you write program code and reference instances that may be instantiated on other network nodes (or in another .NET application domain within the same machine) as real components, you must never cast into concrete .NET classes. Method calls must then always be made using ACUrlCommand or ExecuteMethod calls, for example.
In this case, you can only work with the following classes or work as a reference:
So that your own class can be instantiated by the iPlus runtime, you must declare it according to the following rules:
Sample Code:
There are a variety of base classes from which you can derive to program your own ACComponent. The following UML diagram shows the most important classes in the iPlus framework from which you should make a derivation (abstract classes are written in italic):
In order to be able to work with your self-defined classes in the iPlus development environment (configure application tree, create designs for your class, store configuration parameters...) they must first be made known.
The iPlus runtime then begins to examine all assemblies in the program directory.
It searches for classes that have an ACClassInfo attribute and registers them in the iPlus database as a known type (you can also define classes that are not indirect derivatives of ACComponent so that they can later be bound to the iPlus controls and rights management can also be done). However, these instances usually have to be instantiated manually). Attention: If the ACClassInfo attribute is forgotten, no properties and methods are analyzed via .NET reflection! The ACClassInfo attribute exists with different constructors, the following parameters are declared, which are necessary, so that the iPlus runtime later knows how to handle this class:
Parameter | Description |
---|---|
string acPackageName | [Mandatory] Assignment to a package name. The package name is used for software licensing with the end customer. |
string | [Mandatory] Translation tuple for the translation of the class. Syntax for translation tuple
Example: en{'My english text'}de{'Mein deutscher Text'} |
Global.ACKinds | [Mandatory] Assignment to a category. The category serves on the one hand to simplify the use of the class in the development environment by showing or hiding certain classes depending on the context in which the class is needed, and on the other hand to program for project-specific logics to handle classes that are not yet instantiated at that time. |
Global.ACStorableTypes acStorableType | [Mandatory] Specifies whether the state of this instance (perilizable properties) may be saved or not. This only works for classes instantiated in the application tree. Classes instantiated in the Root project are usually not perilizable. Multiple instantiatable classes are derivatives of ACBSO (business objects) in the rules. In this case, isMultiInstance must have the value True. |
bool isMultiInstance | [Mandatory] Indicates whether the class can be instantiated more than once as a child object. Since the ACIdentifier must be unique in the member list/child list, the iPlus runtime automatically assigns a sequential instance number when a new instance has to be created. This instance number is appended to the ACIdentifier string by means of brackets. Example: "BSOMaterial(1), BSOMaterial(2)". |
bool isRightmanagement | [Optional] Flag whether this class is responsible for rights management and whether rights for properties, methods and designs can be assigned in group management. |
string pwInfoACClass | [Optional] Only relevant for classes that are derivatives of PAProcessFunction. pwInfoACClass specifies the class name of the workflow class (a derivative of PWNodeProcessMethod) that is compatible with this PAProcessFunction. Other wording: Specifies the workflow class that can call this function and knows its parameter list. |
string qryConfig | [Optional] Only relevant for classes that are derivatives of ACBSONav (Navigable Business Objects). qryConfig specifies the name of the primary ACQueryDefinition to be loaded by default to filter the records displayed in Explorer. You can use the iPlus development environment to look up which queries exist in the path \Root\Queries. New queries are automatically entered by declaring the ACQueryInfoPrimary attribute using an entity class and then starting the program with Ctrl-Login. |
string bsoConfig | [Optional] Only relevant for classes that are entity classes. bsoConfig specifies the name of the business object class that is responsible for managing this entity class. If this entity class is displayed in an "item control" such as a combo box, you can use the context menu to navigate to the relevant business object and display or manage the corresponding entity. |
Int16 sortIndex | [Optional] Sort sequence for presenting the class in the iPlus development environment. |
object[] acClassChilds | [Optional] Array to define relationships to other entity objects. Example: [ACQueryInfoPrimary(Const.PackName_VarioMaterial, Const.QueryPrefix + Partslist.ClassName, "en{'Bill of Materials'}de{'Stückliste'}", typeof(Partslist), Partslist.ClassName, "PartslistNo,PartslistName", "PartslistName", |
Each constructor of a class derived from ACComponent must have the same signature:
Parameter | Beschreibung |
---|---|
ACClass acType | The table ACClass contains meta information for a class that is necessary for iPlus runtime to be able to instantiate this class. This includes the following properties/table fields:
ACClass inheritance relationships are often virtual. This means that although the same .NET type is created, it is two different types or instances from the point of view of the iPlus framework. Each instance defined in the application project is automatically a new ACClass that is virtually inherited. However, from a .NET point of view, the same .NET type is instantiated if the AssemblyQualifiedName is the same for two different instances. |
IACObject | Instances that are not derivatives of ACBSO (usually persistent instances in application trees) gets an ACClassTask object as "content" passed. ACClassTask table entries ensure that the state of all persistable instances in the application trees is persisted and that after the restart of the iPlus service, the last state of the process (all object states before the last shutdown) can be restored again. For dynamic instances (derivatives of ACBSO, derivatives of PARole ...) that are not persistable this paramater usually set to null. |
IACObject | Parent-ACComponent under which this instance is created as a child object. |
ACValueList parameter | Individual construction parameters are passed via ACValueList. An ACValueList is a list that contains entries from ACValue. ACValue is a class that has essentially three properties:
|
string acIdentifier = "" | Unique ID, within the child instances of the Parent ACComponent, which this instance will receive. If string is empty, the runtime assgins the ID itself using the ACType parameter identifier. |
The meta information about the construction parameters that a class expects in the "ACValueList parameter" should be defined via the ACClassConstructorInfo attribute class. The ACClassConstructorInfo attribute class is only an object array, which in turn contains entries with object arrays (see code example above). The inner object[] entries may only contain three entries in the following order:
Index 0: string | Name of the parameter that is later in the ACIdentifier of the ACValue entry. |
Index 1: Global.ParamOption | Specifies whether the parameter is Mandatory or Optional. |
Index 2: | .NET-Typ, of the parameter value. |
Whenever you have made changes to your classes, properties or methods and these have the attribute classes ACClassInfo, ACPropertyInfo, ACMethodInfo .... so that they are announced in the iPlus type system, you must
In the previous section you have learned how to start and stop ACComponents via ACUrlCommand. You can do the same directly without ACUrlCommand.
The following methods (different signatures) are defined in the ACComponent class for this purpose:
public virtual IACComponent StartACComponent(
string acIdentifier,
object content,
object[] acParameter,
ACStartCompOptions startOptions = ACStartCompOptions.Default)
public virtual IACComponent StartACComponent(
ACClass acClass,
object content,
ACValueList parameterList,
Global.ACStartTypes startChildMode = Global.ACStartTypes.Automatic,
bool asProxy = false,
string acIdentifier = "")
public virtual IACComponent StartACComponent(
ACChildInstanceInfo instanceInfo,
Global.ACStartTypes startChildMode = Global.ACStartTypes.Automatic,
bool asProxy = false,
string acNameInstance = "")
In the parameter "acIdentifer" you pass the name of the child class/instance that was defined by the development environment in the application tree below the class you are currently in (this-Pointer). If no class with this ACIdentifier could be found in the application tree, the system checks whether it is a business object class (derived from ACBSO). If so, a new dynamic "child instance" is created below the instance in which they are currently located.
The parameter "object content" is passed to the second contructor parameter "IACObject content" during construction.
The parameter "object[] acParameter" must contain the parameters that are passed to the fourth constructor parameter as the "ACValueList parameter". You can do this in two different ways:
The following methods (different signatures) are defined in the ACComponent class for this purpose:
public virtual bool Stop()
Method to stop yourself (this).
public bool StopACComponent(string acIdentifier, bool deleteACClassTask = false)
Method to stop a child component with an acIdentifier.
public bool StopACComponent(IACComponent acComponent, bool deleteACClassTask = false)
Method to stop the acComponent passed.
You can use the following methods to search for instances in the application tree:
public IACComponent FindParentACComponent(Type type)
public IACComponent FindParentACComponent(ACClass type)
public TResult FindParentACComponent<TResult>() where TResult : IACComponent
public TResult FindParentACComponent<TResult>(Func<IACComponent, bool> selector) where TResult : IACComponent
public List<IACComponent> FindChildACComponents(Type typeOfComponent, int maxChildDepth = 0)
public List<IACComponent> FindChildACComponents(ACClass acClass, int maxChildDepth = 0)
public List<TResult> FindChildACComponents<TResult>(int maxChildDepth = 0) where TResult : IACComponent
public List<TResult> FindChildACComponents<TResult>(Func<IACComponent, bool> selector, Func<IACComponent, bool> deselector = null, int maxChildDepth = 0) where TResult : IACComponent
Examples:
We use cookies to provide you with the best possible experience. They also allow us to analyze user behavior in order to constantly improve the website for you.