Friday, January 29, 2010

Wie man die Modifier Private, Protected und Abstract umgeht

Auf Wunsch der Leserschaft werden meine Beiträge nun auch in deutscher Sprache veröffentlicht. Dieser Post bezieht sich auf den englischsprachigen Post How to ignore Private, Protected and Abstract modifiers. 

Bisher habe ich mich immer über die Meldungen "Statisches Konstrukt implementieren, um Änderungen zu ermöglichen." und "'New' muss den Status 'protected' aufweisen." gewundert.

Sagen wir, wir möchten eine neue Verarbeitung mit einer RunBaseBatch-Klasse realisieren: Wenn wir nun den Optimalen Verfahren folgen, werden wir folglich die new()-Methode Protected deklarieren. Aber wie soll nun das Framework der Stapelverarbeitung jemals ein Objekt aus dieser Klasse erstellen, sollte der Benutzer die Verarbeitung in den Stapel stellen?

Weil die new()-Methode ja nun mit dem Modifier Protected geschützt ist, kann aus der Klasse kein Objekt mit new() erstellt werden, richtig?
Theoretisch ja, allerdings hat man da die Rechnung ohne die Möglichkeiten der Reflection-Technik in AX gemacht.

Wie im Allgemeinen bekannt, ist es möglich mit dem Kernelobjekt vom Typ DictClass (oder mit dem vielleicht besser bekannten abgeleiteten Typ SysDictClass) dynamisch Objekte zu erstellen und Objektmethoden aufzurufen. Nach ein paar Tests hat sich herausgestellt, dass das DictClass Objekt seinen ganz eigenen Regeln folgt, wenn es um die Möglichkeiten der Codeverarbeitung geht.

Mit einem DictClass-Objekt kann man Objekte aus Klassen erstellen, die dafür gar nicht geeignet sind. So kann man mit der makeObject()-Methode:
  • Objekte aus abstrakten Klassen erzeugen 
  • Objekte erstellen auch wenn die new()-Methode Private oder Protected deklariert ist (die new()-Methode wird dann auch wirklich durchlaufen) 
  • Objekte erstellen, auch wenn die jeweilige Klasse nicht alle abstrakten Methoden überschrieben hat 
Aber die Möglichkeiten mit dem DictClass-Objekt enden nicht einfach damit verbotene Objekte zu erstellen. Es ist auch möglich:
  • Member- und statische Methoden ungeachtet der Modifier protected, private oder abstract aufzurufen (mit callObject() und callStatic()
Als wäre das nun nicht schon genug der Blasphemie: das DictTable-Objekt verfügt ebenfalls über diese Verhaltenseigenschaften. Mit callStatic() und callObject() des DictTable-Objektes kann jede beliebige Tabellenmethode aufgerufen werden.

Fazit: In AX existieren zwar hässliche, aber äusserst effektive Verfahren um Codesicherheit und Kompilerprüfungen zu umgehen. Auch wenn es möglich ist, diese Tricks einzusetzen, rate ich dringend davon ab. Dieser Artikel soll nur zeigen was möglich ist, das heisst aber nicht, dass es auch sinnvoll ist.

(Inhalt bezieht sich auf AX 2009)

No comments:

Post a Comment