C# language
C# language as an SDO method is chosen for specific applications in processing methods, the specifics of which do not correspond to the choice of another method. These aggregates are created as elements of a public class property.
For a given class to serve as a collection of aggregates, it must meet the following requirements:
- It must be public, cannot be static or abstract.
- It cannot have the sealed modifier.
- It must have the partial modifier (the reason for this requirement is explained below).
- The namespace must follow this format:
<<namespace name>>.<<input/output path>>
Similarly to the class, property elements must meet the following requirements:
- It must be a type accepted by SDO, which means one of the following types:
- String
- DateTime
- Decimal
- Double
- Guid
- Boolean
- It must have the virtual modifier.
- It cannot have a set clause.
- It must have a get clause.
- It must be public (with the public modifier).
All properties that meet the above conditions are added as aggregates to the output path and can be used by other aggregates.
To create an SDO in the C# language:
- In the main window, select the add icon in the upper left corner or from the main menu File>New or from the version server context menu New element.
- Then select SDO in the popup window. Select C# Code as the Transformation Type and click OK.

- After selecting the above, a tab is displayed that allows you to create the code where the comments provide hints on where the transformation code should go.
- The first step is to select the Data Space. Be sure to additionally modify the
namespacein the code accordingly as well. The data space in the top selection window must be identical to the one in the code.

In the following case, a Data space has been selected in the Output path field, which is subordinate to the path in the Input path field, which is correct from the point of view of accessing the tree-based data structure. In this case, the system only reports validation errors regarding the correct placement of the code in the namespace, which should be configured as follows:
namespace: ClientsTransaction.TRANSACTIONS.ACCOUNT

The reverse is not correct and an error will be displayed.

Additionally, the code generated in C# can use all aggregates available in the input/output path – they can be referenced via the this clause. These aggregates are part of the definition of the edited class; however, to avoid additional complexity, they are not visible in the user’s aggregate code (this is the reason why the partial keyword is required for every class that contains aggregates – all existing aggregates are generated in this part of the class that is invisible to the user). The code defining an aggregate can also refer not only to the current path but also to other aggregates and elements of the data space tree. Through the this clause, the class also has access to child elements as well as the “parent” element – to reference the parent, the Parent property must be used.
Requirement (Mandatory vs Optional)
Each aggregate in its declaration must specify whether it is mandatory, meaning whether the value it returns can be null. The types returned by aggregates can be divided into two groups: reference types, which include System.String, and structures, which include all other types.
In the case of structures, by default they cannot return null, which means they are treated as mandatory. To make an aggregate that is a structure optional, it must be declared as a nullable type, using either the generic type Nullable<T> or the shorthand ?
public virtual decimal? NullableField
{
get {return 0:}
}
public virtual Nullable<decimal> NullableField2
{
get {return -1:}
}
In the case of the System.String type, which is a reference type, the situation is different: although it is a reference type and can accept a null value, by default we assume the aggregate is mandatory, meaning the property cannot return null (returning null will cause an error during aggregate calculation). If we want the aggregate to be optional, the property must be decorated with the CanBeNull attribute.
/// <summary> Mandatory aggregate cannot return a null value. </summary>
public virtual String MandatoryAggregate
{
get {return "";}
}
/// <summary> Nullable aggregate - can return a null value. </summary>
[CanBeNull]
public virtual String NullableAggregate
{
get {return null;}
}

Dependencies on Other Aggregates
SDO requires that at design time all dependencies are known, meaning all aggregates needed to calculate the designed aggregate. Appropriate analysis is performed at design time, and during execution, the engine that runs aggregate calculation ensures that references can be made only to dependent elements that have been previously declared or calculated.
By default, the C# language analyzer is able to resolve all dependent aggregates, so there is no need to manually describe inputs. However, there may be situations when the analyzer is not able to resolve required dependencies on its own (for example, when reflection is used). In such cases, the aggregate must be marked with the DependsOn attribute.
[DependsOn("CA_FV_1_6")]
public virtual decimal AgregatZRefleksja
{
get
{
var propertyInfo = this.GetType().GetProperty("CA_FV_1_6");
decimal value - (decimal)propertyInfo.GetValue(this);
return value * 2;
}
}
