DevExpress bietet Möglichkeiten, um die Formeln (Criteria Operators) zu erweitern. Für verschiedene Möglichkeiten steht jeweils ein Interface zur Vergügung, wobei auch eine Kombination möglich ist und sinnvoll sein kann.

Diese Möglichkeiten sind für den Einsatz in Business App nicht ausreichend. Da hier die Anforderung besteht komplexe oder variable Criteria Operators für die Konfiguration zu vereinfachen.

Zu beachten

  • Der Name der Klasse muss mit dem Namen der Implementierten Custom-Funktion übereinstimmen. Der Namespace ist egal.
  • Wenn in einem Modul oder Projekt eine gleichnamige Klasse definiert, wir die Klasse des Core bzw. des darunter liegenden Moduls nicht mehr verwendet und nur noch die Überladung benutzt. Es kann dabei optional von der ursprünglichen Implementierung geerbt werden.
  • Die Registrierung von eigenen Funktionen erfolgt in BA automatisch.

Makro Funktionen (BA intern)

Ziel unserer Erweiterung von Custom Criteria Operators Funktionen ist es Teile eines Criteria Operator Ausdrucks zu ersetzen. Also sozusagen eine Art Makro. Entsprechende Erweiterungen im Core befinden sich im Packet BA.Core.CriteriaOperators.Functions. Um eine Erweiterung zu implementieren, muss das Interface ICriteriaOperatorBAFunction implementiert werden.

Dieses Interface kann auch mit den folgenden Interfaces kombiniert werden, wenn nur ein Teil der Funktionalität über Standard Criteria implementiert ist.

Beispiel für ICriteriaOperatorBAFunction

Zuerst sollte man die Parameter prüfen, ob diese der erwarteten Anzahl und Typen entsprechen. Wenn nicht sollten Aussagekräftige Ausnahmen in Anwendersprache geworfen werden. Diese werden bei der Verwendung der Funktion in einem Formelfeld dem Konfigurator angezeigt.

Wenn alles passt wird am Ende die neue Formel zurückgegeben.

public class BAExample : ICriteriaOperatorBAFunction
{
    public virtual CriteriaOperator GetCriteria(CriteriaOperatorBAFunctionPatcher visitor, FunctionOperator function)
    {
        CriteriaOperatorCollection operands = function.Operands;
        if (operands == null || operands.Count != 1 || !(operands[1] is OperandValue operand1) || !(operand1.Value is string stringValue))
            throw new ArgumentException("Es wird ein String Parameter erwartet");

        return new OperandValue(stringValue);
    }
}

In .Net Ausführbar (DevExpress)

Mit dem Interface ICustomFunctionOperatorConvertibleToExpression kann die eigene Criteria-Funktion in .NET ausgeführt werden. Klassen, die nur dieses Interface implementieren, funktionieren in Datenbankabfragen (Ansichten, etc.) nicht. Dazu muss zusätzlich auch ICustomFunctionOperatorFormattable implementiert werden.

Technisch gesehen müssen zwei Interfaces programmiert werden

  • ICustomFunctionOperator
    Dies wird für den Criteria-Interpreter von DevExpress verwendet, der Criteria-Ausdrücke zur Laufzeit interpretiert. Das wird z.B. im Kontext von Reports verwendet.
  • ICustomFunctionOperatorConvertibleToExpression
    Das ist für kompilierbare Criteria-Funktionen. Diese werden von BA überall verwendet außer in Ansichten und Reports. Aus den .NET Criteria wird dann zuerst ein LINQ-Expression-Tree erzeugt, welcher dann weiter in .NET IL und Maschinencode übersetzt wird.

Datenbankabfragen erweitern (DevExpress)

Das Interface ICustomFunctionOperatorFormattable ist ausschließlich für Datenbankabfragen und erlaubt es, individuell angepasstes SQL zu erzeugen. Die Implementierung muss dabei auf eventuelle Besonderheiten unterschiedlicher Datenbanken Rücksicht nehmen.

Klassen, die nur dieses Interface implementieren, funktionieren im .NET-Kontext nicht. Dazu muss zusätzlich auch ICustomFunctionOperatorConvertibleToExpression implementiert werden.