Skip to main content

xSuite Interface Windows Prism 5.x – Online-Hilfe

Benutzerdefinierte Makrofunktionen

Eigenerstellte Makrofunktionen werden zentral in einer gemeinsamen Schnittstellenbibliothek implementiert, deren Dateipfad in der globalen Konfigurationseigenschaft General.CustomMacrosAssemblyPath anzugeben ist. Anders als bei den eigenen Modulen sind die Namen der Klassen hier fest vorgegeben, wobei es für jede Art von Makrofunktion eine Klasse gibt, in der alle betreffenden Methoden zu implementieren sind:

  • CustomFieldMacros: Feldmakrofunktionen

  • CustomDocumentMacros: Dokumentmakrofunktionen

  • CustomFileMacros: Dateimakrofunktionen

  • CustomGlobalMacros: globale Makrofunktionen

Die Namen der Methoden sind frei wählbar, sie müssen aber – genau wie die Klassen – als public und static deklariert sein und die Namen dürfen nicht mit denjenigen von internen Makrofunktionen kollidieren. Außerdem müssen die Methoden je nach Art eine ganz bestimmte Signatur haben, die in Form eines Delegaten im Namensraum XSuite.Interface.CustomModules.Macros der Datei CustomModules.dll definiert ist. Allen gemein als Aufrufparameter sind eine Liste der benutzerdefinierten Parameter für genau diese Makrofunktion, eine Aufstellung aller im jeweiligen Kontext verfügbaren Dokument-/System-/Umgebungsvariablen und eine Logging-Komponente.

Delegat

Beschreibung

object CustomFieldMacroFunction(
   IList<object> customParams, 
   Document document, 
   IDictionary<string, object> variables,
   ICustomLogger logger)

Als spezifischen Aufrufparameter erhält eine Feldmakrofunktion das vollständige Dokumentobjekt, um z.B. auch (lesend) auf Feldinhalte zugreifen zu können, die nicht als benutzerdefinierter Parameter übergeben werden. Als Ergebnis der Funktionsausführung wird einzig der Rückgabewert übernommen, mögliche Änderungen direkt am Dokument hingegen werden ignoriert. Dieser Wert muss einem vom Makrointerpreter unterstützten .NET-Datentyp entsprechen oder zumindest in diesen konvertierbar sein: string (Textwert), double (Zahlenwert), bool (Wahrheitswert), System.DateTime (Datumswert) und System.Array.

void CustomDocumentMacroFunction(
   IList<object> customParams, 
   Document document, 
   IDictionary<string, object> variables,
   ICustomLogger logger)

Eine Dokumentmakrofunktion hat die gleiche Signatur wie ein Feldmakro. Eine Dokumentmakrofunktion hat jedoch keinen Rückgabewert, sondern die Modifikationen sind direkt am übergebenen Dokumentobjekt durchzuführen. Es werden alle Änderungen an bestehenden Feldinhalten übernommen; das Hinzufügen neuer Felder ist hingegen nur im Kontext von Tabellenfeldern durch das Einfügen neuer Zeilen zulässig. Eine solche Zeile muss nicht zwingend alle deklarierten Felder umfassen, da die fehlenden vom Programm ergänzt und mit ihren Initialwerten belegt werden. Neu gesetzte Feldwerte müssen einem vom Makrointerpreter unterstützten .NET-Datentyp entsprechen oder zumindest in diesen konvertierbar sein.

Neben Feldänderungen werden auch solche an den Metadaten und externen Schlüsseln des Dokumentes und seiner Dateianlagen übernommen.

IList<Attachment> CustomFileMacroFunction(
   IList<object> customParams, 
   List<Attachment>
filteredAttachments, 
   Dictionary<string, object> variables,
   CustomLogger logger)

Eine Dateimakrofunktion erhält als spezifischen Aufrufparameter diejenigen Dateianlagen, die gemäß des Dateinamensfilters (erster Standardparameter eines jeden Dateimakros) als Quelldateien für die Makroausführung dienen sollen. Anders als bei internen Dateimakros wird dabei nicht unterschieden, ob das Makro eine oder mehrere Eingabedateien erwartet, um dann mehrfach mit je einer Datei oder nur einmal mit allen Dateien aufgerufen zu werden. Für eigene Dateimakros findet immer letztere Art von Aufruf statt, so dass eine Einzeldateiverarbeitung ggf. in der eigenen Verarbeitungslogik berücksichtigt werden muss. Übernommen und als neue Dateianlagen dem Dokument hinzugefügt werden all diejenigen, die das Makro als Funktionsergebnis zurückgibt. Die dabei mitgelieferten Dateinamen dienen als Grundlage zur Bildung der Zieldateinamen gemäß dem definierten Muster (zweiter Standardparameter mit Standardwert %FileName%).

Im Kontext eines Dateimakros werden die Binärdaten der Dateianlagen grundsätzlich als Streams in der Eigenschaft .FileData übergeben, d.h. der .FilePath hat hier keine Relevanz.

void
CustomGlobalMacroFunction(
   IList<object> customParams,
   Dictionary<string, object> variables, 
   CustomLogger logger)

Eine globale Makrofunktion hat keine spezifischen Aufrufparameter, da kein Verarbeitungskontext eines Stapels oder Dokumentes vorliegt und ihr Einsatzzweck vielfältig sein kann. Ein direkter Zugriff auf interne Ressourcen wie Storage oder Verwaltungsdatenbank ist für ein externes Makro derzeit nicht vorgesehen, so dass ein solcher bestenfalls durch Aufbau einer eigenständigen Verbindung zu der Ressource bewerkstelligt werden kann.

In einem Makroausdruck werden die eigenen Funktionen auf dieselbe Weise aufgerufen wie die internen, nämlich direkt über ihren Namen, so wie die betreffende Methode in der Klassenbibliothek genannt worden ist, und mit ihren benutzerdefinierten Parametern. Die Werte dieser variabel langen Parameterliste werden der eigenen Methode, die die Makrofunktion implementiert, gebündelt im Aufrufparameter customParams übergeben. Da der interne Makrointerpreter keinen benannten Parameter unterstützt, sind sie dabei einzig über ihre Reihenfolge identifizierbar.

Weil die internen Makrofunktionen über eine allgemeine Möglichkeit zur Datentyp- und Pflichtfeldprüfung verfügen, wird diese auch den externen Funktionen zur Verfügung gestellt. So kann grundlegend sichergestellt werden, dass die übergebenen Werte den Anforderungen der eigenen Makros genügen, ohne die Prüfungen vollständig selbst implementieren zu müssen. Die Übergabe erfolgt dennoch als allgemeiner object-Typ, so dass im eigenen Code zumindest ein Cast in den konkreten Zieltyp notwendig sein wird. Im Namensraum XSuite.Interface.CustomModules.Macros der CustomModules.dll sind 3 spezielle Attribute definiert, mit denen die eigenen Methoden ausgezeichnet werden können:

  • CustomParamsTypeAttribute: Datentyp des Parameters, z. B. typeof(string) (Standardwert), ggf. Versuch der Konvertierung

  • CustomParamsRequiredAttribute: Pflichtfeld, true oder false (Standardwert)

  • CustomParamsDefaultAttribute: Default-Wert bei fehlendem Parameterwert

Die Attribute nehmen jeweils eine variable Anzahl von Werten entgegen, die in ihrer Reihenfolge den benutzerdefinierten Makroparametern entsprechen. Wenn ein Makro z. B. 3 Parameter der Typen string, string und bool erwartet, ist das folgende Attribut anzugeben:

[CustomParamsType(typeof(string), typeof(string), typeof(bool))]

Zulässige Datentypen bei der Typprüfung und bei den Standardwerten sind diejenigen, die vom internen Makrointerpreter unterstützt werden oder implizit konvertiert werden können: string (Textwert), double (Zahlenwert), bool (Wahrheitswert), System.DateTime (Datumswert) und System.Array. Für ganzzahlige Werte ist in diesem Kontext zusätzlich der long-Typ nutzbar. Bei der Typprüfung von Aufzählungswerten kann nur allgemein auf den Array-Typ geprüft werden, nicht aber auf den Typ der enthaltenen Elemente.

Zusätzlich zu den 3 obigen Attributen ist das Attribut RequiresFileStreamsAttribute verfügbar, das einen einzelnen booleschen Wert entgegennimmt. Es ist nur für Feld- und Dokumentmakrofunktionen relevant, bei denen über diesen Wert bestimmt wird, ob in das an sie übergebene Dokumentobjekt auch die Streams der enthaltenen Dateianlagen geladen werden sollen. Da die meisten Makros keinen Zugriff auf die Binärdaten dieser Dateien benötigen, ist der Standardwert false, um nicht unnötig Speicher zu belegen.

Benutzerdefinierte Makrofunktionen werden auch im Makroeditor-Dialog des Konfigurators angezeigt. Um dabei nicht nur ihren Namen, sondern ähnlich wie bei den internen Makros auch eine Beschreibung sowie Informationen zu Parametern und Rückgabewert darzustellen, werden im eigenen Programmcode gesetzte XML-Kommentare zu den betreffenden Methoden ausgewertet, nämlich konkret die Standard-Tags <summary>, <param> und <returns>. Ist die missbräuchliche Verwendung von <param> nicht erwünscht, kann stattdessen das Nicht-Standard-Tag <customparam> genutzt werden, das bis auf den Namen die gleiche Syntax hat. Denn streng genommen bezieht sich <params> auf alle Parameter in der die Makrofunktion implementierenden Methode und nicht auf die Einzelwerte innerhalb des customParams-Auflistung. Um überhaupt Zugriff auf die XML-Kommentare zu erhalten, benötigt xSuite Interface eine entsprechende XML-Dokumentationsdatei, die zu der eigenen Klassenbibliothek generiert werden und unter dem gleichen Basisnamen wie die .dll-Bibliotheksdatei im selben Verzeichnis wie diese liegen muss. Aktiviert werden kann diese Generierung z.B. direkt in der Projektdatei der Klassenbibliothek:

<PropertyGroup>  
   <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

Das folgende Beispiel zeigt die Nutzung von XML-Kommentaren und Attributen für eine Feldmakrofunktion. Zwei benutzerdefinierte Parameter der Typen long und bool werden erwartet (Attribut CustomParamsType). Der erste Parameter ist verpflichtend (Attribut CustomParamsRequired). Für den zweiten Parameter fehlt diese Angabe, sodass implizit false gilt. Der zweite Parameter hat den Default-Wert true (Attribut CustomParamsDefault). Der Wert null beim ersten Parameter bedeutet, dass kein Default-Wert definiert ist. Der erste Parameter ist ein Pflichtparameter und wird nur als Platzhalter angegeben, um die korrekte Reihenfolge einzuhalten.

public static class CustomFieldMacros
{
   /// <summary>Custom field macro sample.</summary>
   /// <customparam name="param1">first parameter</customparam>
   /// <customparam name="param2">second parameter</customparam>
   /// <returns>The result value.</returns>
   [CustomParamsType(typeof(long),
typeof(bool))]
   [CustomParamsRequired(true)]
   [CustomParamsDefault(null, true)]
   public static object
CustomFieldMacroSample(
      IList<object> customParams,
      Document document,
      IDictionary<string, object>
variables,
      ICustomLogger logger)
   {
      throw new NotImplementedException();
   }
}