You can call .NET Framework type members, including methods, properties, and constructors, from C/AL code with the DotNet data type for C/AL variables. This section provides an overview of the DotNet data type, guidelines on its use, and aspects about calling members of a .NET Framework type. For information about how to create and use a DotNet variable to call members of a type, see How to: Call .NET Framework Members from C/AL Code.
DotNet Data Type
The DotNet type resembles the Automation type in C/AL except that it references a .NET Framework type in an assembly. Assemblies can be either part of assemblies that are installed in the global assembly cache or custom assemblies that you have installed for Microsoft Dynamics NAV. For more information about installing assemblies in global assembly cache, see Assembly Installation in the GAC.
After you have defined a DotNet variable, you can call it in C/AL code to instantiate members of a .NET Framework type.
A constructor is a method that creates an instance of an object and prepares it for use. Before you use a DotNet variable, you should verify whether the variable is static or is an object instance because this determines whether you have to use a constructor.
- Static variables do not require a constructor
because they do not have an instance.
- Object instance variables require a
constructor because they must be created before they can be
To find the constructor and other methods and property for your object, in Object Designer, click Symbol.
Static and Instance Method Calls
Methods that you call from C/AL code can be either static or instance methods.
- You use the same syntax to call static and
- Calling static methods provides a factory
pattern for creating object instances. For example, to create a new
System.TimeZoneInfo object, you call the type’s
System.TimeZoneInfo.Local static method with the following
zone := zone.Local;
- A static class or object is loaded once per
Microsoft Dynamics NAV Server instance, and the class or object is
shared between all clients that are connected to the server
instance. The data that is maintained by the static class or object
is visible by all clients that use the type. You should consider
this in your .NET Framework interoperability design to help avoid
disclosing private information.
A C# indexer is represented as an Item property
in C/AL. For example, in C#, the following code sets an array
N to the value
arrayVariable[N] = M;
In C/AL, the corresponding code is as follows:
arrayVariable.Item(N) := M;
Indexers can also be overloaded. In Object Designer, click C/AL Symbol Menu to see the parameters and return types for the indexer.
Indexers for lists and arrays that are defined by .NET Framework variables are zero-based, which means that they start at 0. Other indexers in C/AL start at 1.
Operators for Comparing .NET Framework Objects
.NET Framework interoperability does not support direct use of operators to compare two DotNet variables. For example, the following scenario is not supported:
IF dotnetVar1 <= dotnetVar2 THEN
If you want to compare two DotNet variables, then you can use the Equals function on the DotNet variables as shown in the following example:
IF dnVersion1.Equals(dnVersion2) THEN …
You can perform comparisons by using .NET Framework methods and properties that return compatible C/AL types because these objects are implicitly converted to C/AL types before the comparison takes place. For example, the following C/AL code includes three DotNet variables for the System.Collections.Generic.List class: dotNetList1, dotNetList2, and dotNetList3. You cannot compare the DotNet variables directly because they do not return C/AL types. You can perform comparisons on the List.Capacity property because the List.Capacity property is a NET Framework integer type that returns a C/AL integer type. For more information about conversion between .NET Framework and C/AL types, see .NET Framework Type Conversion.
dotNetList1 := dotNetList1.List(5); dotNetList2 := dotNetList2.List(10); dotNetList3 := dotNetList3.List(5); IF dotNetList1.Capacity <> dotNetList3.Capacity THEN ERROR('List1 and List3 should have the same capacity.'); IF dotNetList1.Capacity = dotNetList2.Capacity THEN ERROR('List1 and List2 should not have the same capacity.'); IF dotNetList1.ToString() <> dotNetList2.ToString() THEN ERROR('List1 and List2 should have the same ToString output.');
Events and Public Fields
Microsoft Dynamics NAV 2009 R2 does not support events and public fields in the .NET Framework.
Long Member Names
There is a limit of 30 characters on member names. To call a constructor that is longer than 30 characters, use the C/AL Symbol Menu because the constructor names are automatically truncated to 30 characters. You cannot directly call methods and properties that are more than 30 characters long because you cannot compile the Microsoft Dynamics NAV object. To resolve this issue, you can create a method that wraps the original method or property and has a name that is 30 characters or fewer. From C/AL code, you can then call the new method instead of the original method or property.
Case Sensitivity in Member Names
NET Framework member names in C/AL code are case-sensitive. If you use the incorrect case when you call a member, then you get an error when you compile the object. This behavior differs from other C/AL variables because you can mix cases and still compile the object. For other C/AL variables, the case is corrected automatically the next time that you open the object.
Local DotNet Variable Limitations
You should not assign a local DotNet variable to global C/AL or .NET Framework objects because the local DotNet variable is disposed when it goes out of scope. If you use the DotNet variable outside the scope of its local function, then you should define it as a global DotNet variable.