programming4us
programming4us
ENTERPRISE

Microsoft Dynamic AX 2009 : Reflection System Functions

- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire
11/16/2013 2:29:22 AM
1. Introduction

Reflection is a programmatic discoverability mechanism of the Microsoft Dynamics AX application model. In other words, reflection provides APIs for reading and traversing element definitions. By using the reflection APIs in the MorphX development environment, you can query metadata as though it were a table, an object model, or a tree structure.

You can do interesting analyses with the reflection information. The Reverse Engineering tool is an excellent example of the power of reflection. Based on element definitions in MorphX, the tool generates Unified Modeling Language (UML) models and Entity Relationship Diagrams (ERDs) that you can browse in Microsoft Office Visio.

Reflection also allows you to invoke methods on objects. This capability is of little value to business application developers who construct class hierarchies properly. For framework developers, however, the power to invoke methods on objects can be valuable. Suppose, for example, you want to programmatically write any record to an XML file that includes all of the fields and display methods. Reflection allows you to determine the fields and their values and also to invoke the display methods to capture their return values.

X++ features a set of system functions that you can use for reflection, as well as three reflection APIs. The reflection system functions follow:

  • Intrinsic functions A set of functions that allow you to refer to an element’s name or ID safely at compile time

  • TypeOf system function A function that returns the primitive type for a variable

  • ClassIdGet system function A function that returns the ID of the class for an instance of an object

These are the reflection APIs:

  • Table data A set of tables that contains all element definitions. The tables give you direct access to the contents of the .aod files. You can query for the existence of elements and certain properties, such as created by and created datetime. You can’t retrieve information about the contents or structure of each element.

  • Dictionary A set of classes that provide a type-safe mechanism for reading metadata from an object model. Dictionary classes provide basic and more abstract information about elements in a type-safe manner. With few exceptions, this API is read-only.

  • Treenodes A class hierarchy that provides the Application Object Tree (AOT) with an API that can be used to create, read, update, and delete any piece of metadata or source code. This API can tell you everything about anything in the AOT. You navigate the tree-nodes in the AOT through the API and query for metadata in a non-type-safe manner.

2. Reflection System Functions

The X++ language features a set of system functions that can be used to reflect on elements. They are described in the following sections.

Intrinsic Functions

You should use intrinsic functions whenever you need to reference an element from within X++ code. Intrinsic functions provide a way to make a type-safe reference. The compiler recognizes the reference and verifies that the element being referenced exists. If the element doesn’t exist, the code doesn’t compile. Because elements have their own life cycles, a reference doesn’t remain valid forever; an element can be renamed or deleted. Using intrinsic functions ensures that you are notified of any broken references at compile time. A compiler error early in the development cycle is always better than a run-time error.

All references you make using intrinsic functions are captured by the Cross-reference tool. So you can determine where any element is referenced, regardless of whether the reference is in metadata or code.

Consider these two implementations.

print "MyClass";          //Prints MyClass
print classStr(MyClass); //Prints MyClass


They have exactly the same result: the string “MyClass” is printed. As a reference, the first implementation is weak. It will eventually break when the class is renamed or deleted, meaning that you’ll need to spend time debugging. The second implementation is strong and unlikely to break. If you were to rename or delete MyClass, you could use the Cross-reference tool to do an impact analysis of your changes and correct any broken references.

Using the intrinsic functions <Concept>Str, you can reference all the elements in the AOT by their names. You can also reference elements that have an ID with the intrinsic function <Concept>Num. Intrinsic functions are not limited to parent objects; they also exist for class methods, table fields, indexes, and methods. More than 50 intrinsic functions are available. Here are a few examples of intrinsic functions.

print fieldNum(MyTable, MyField);   //Prints 50001
print fieldStr(MyTable, MyField); //Prints MyField
print methodStr(MyClass, MyMethod); //Prints MyMethod
print formStr(MyForm); //Prints MyForm


An element’s ID is assigned when the element is created. The ID is a sequential ID dependant on an application model layer. In the preceding example, 50001 is the ID assigned to the first element created in the USR layer.

Two other intrinsic functions are worth noting: identifierStr and literalStr. IdentifierStr allows you to refer to elements when a more feature-rich intrinsic function isn’t available. IdentifierStr provides no compile-time checking and no cross-reference information. Using the identifierStr function is much better than using a literal, because the intention of referring to an element is captured. If a literal is used, the intention is lost—the reference could be to user interface text, a file name, or something completely different. The Best Practices tool detects the use of identifierStr and issues a best practice warning.

The Dynamics AX runtime automatically converts any reference to a label identifier to the label text for the label identifier. In most cases, this behavior is what you want; however, you can avoid the conversion by using literalStr. LiteralStr allows you to refer to a label identifier without converting the label ID to the label text, as shown here.

print "@SYS1";             //Prints Time transactions
print literalStr("@SYS1"); //Prints @SYS1


In the first line of the example, the label identifier (@SYS1) is automatically converted to the label text (Time transactions). In the second line, the reference to the label identifier isn’t converted.

TypeOf System Function

The TypeOf system function takes a variable instance as a parameter and returns the primitive type of the parameter. Here is an example.

int i = 123;
str s = "Hello world";
MyClass c;
Guid g = newGuid();

print typeOf(i); //Prints Integer
print typeOf(s); //Prints String
print typeOf(c); //Prints Class
print typeOf(g); //Prints Guid
pause;


The return value is an instance of the Types system enumeration. It contains an enumeration for each primitive type in X++.

ClassIdGet System Function

The ClassIdGet system function takes an object as a parameter and returns the class ID for the class element of which the object is an instance. If the parameter passed is Null, the function returns the class ID for the declared type, as shown here.

MyBaseClass c;
print classIdGet(c); //Prints 50001

c = new MyDerivedClass();
print classIdGet(c); //Prints 50002
pause;


This function is particularly useful for determining the type of an object instance. Suppose you need to determine whether a class instance is a particular class. The following example shows how you can use ClassIdGet to determine the class ID of the _anyClass variable instance. If the _anyClass variable really is an instance of MyClass, it’s safe to assign it to the variable myClass.

void myMethod(object _anyClass)
{
MyClass myClass;
if (classIdGet(_anyClass) == classNum(MyClass))
{
myClass = _anyClass;
...
}
}


Notice the use of the intrinsic function, which evaluates at compile time, and the use of classIdGet, which evaluates at run time.

Because inheritance isn’t taken into account, this sort of implementation is likely to break the object model. In most cases, any instance of a derived MyClass class should be treated as an actual MyClass instance. The simplest way to handle inheritance is to use the is and as static methods on the SysDictClass class. You’ll recognize these methods if you’re familiar with C#. The is method returns true if the object passed in is of a certain type, and the as method can be used to cast an instance to a particular type. The as method returns null if the cast is invalid.

These two methods also take interface implementations into account. So with the as method, you can cast your object to an interface. Here is a revision of the preceding example using the as method.

void myMethod(object _anyClass)
{
MyClass myClass = SysDictClass::as(_anyClass, classNum(MyClass));
if (myClass)
{
...
}
}


Here is an example of an interface cast.

void myMethod2(object _anyClass)
{
SysPackable packableClass =
SysDictClass::as(_anyClass, classNum(SysPackable));
if (packableClass)
{
packableClass.pack();
}
}
Other  
  •  Microsoft Enterprise Library : Banishing Validation Complication - Diving in With Some Simple Examples (part 4)
  •  Microsoft Enterprise Library : Banishing Validation Complication - Diving in With Some Simple Examples (part 3)
  •  Microsoft Enterprise Library : Banishing Validation Complication - Diving in With Some Simple Examples (part 2)
  •  Microsoft Enterprise Library : Banishing Validation Complication - Diving in With Some Simple Examples (part 1)
  •  Microsoft Enterprise Library : Banishing Validation Complication - How Do I Use The Validation Block?
  •  Microsoft Enterprise Library : Banishing Validation Complication - What Does the Validation Block Do? (part 2)
  •  Microsoft Enterprise Library : Banishing Validation Complication - What Does the Validation Block Do? (part 1)
  •  Microsoft Enterprise Library : A Cache Advance for Your Applications - How Do I Use the Caching Block (part 4) - Refreshing the Cache, Loading the Cache
  •  Microsoft Enterprise Library : A Cache Advance for Your Applications - How Do I Use the Caching Block (part 3) - Removing Items from and Flushing the Cache
  •  Microsoft Enterprise Library : A Cache Advance for Your Applications - How Do I Use the Caching Block (part 2)
  •  
    Top 10
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
    - Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
    - Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    programming4us programming4us
    programming4us
     
     
    programming4us