Monday, August 6, 2018

Method wrapping and Chain of Command (CoC) in D365

Class extension via method wrapping and Chain of Command (CoC)

The functionality for class extension, or class augmentation, has been improved in Microsoft Dynamics 365 for Finance and Operations. You can now wrap logic around methods that are defined in the base class that you're augmenting. 
  • You can extend the logic of public and protected methods without having to use event handlers. 
  • When you wrap a method, you can also access public and protected methods, and variables of the base class. 
In this way, you can start transactions and easily manage state variables that are associated with your class.

For example, a model contains the following code.

class BusinessLogic1 { str DoSomething(int arg) { … } }

You can now augment the functionality of the DoSomething method inside an extension class by reusing the same method name. An extension class must belong to a package that references the model where the augmented class is defined.

[ExtensionOf(ClassStr(BusinessLogic1))] final class BusinessLogic1_Extension { str DoSomething(int arg) { // Part 1 var s = next DoSomething(arg + 4); // Part 2 return s; } }

In this example, the wrapper around DoSomething and the required use of the next keyword create a Chain of Command (CoC) for the method. CoC is a design pattern where a request is handled by a series of receivers. The pattern supports loose coupling of the sender and the receivers.

We now run the following code.

BusinessLogic1 c = new BusinessLogic1(); info(c.DoSomething(33));

When this code is run, the system finds any method that wraps the DoSomething method. The system randomly runs one of these methods, such as the DoSomething method of the BusinessLogic1_Extension class. When the call to the next DoSomething method occurs, the system randomly picks another method in the CoC. If no more wrapped methods exist, the system calls the original implementation.

Capabilities

The following sections give more details about the capabilities of method wrapping and CoC.

Wrapping public and protected methods

Protected or public methods of classes, tables, or forms can be wrapped by using an extension class that augments that class, table, or form. The wrapper method must have the same signature as the base method.
  • When you augment form classes, only root-level methods can be wrapped. You can't wrap methods that are defined in nested classes.
  • Only methods that are defined in regular classes can be wrapped. Methods that are defined in extension classes can't be wrapped by augmenting the extension classes.

What about default parameters?

Methods that have default parameters can be wrapped by extension classes. However, the method signature in the wrapper method must not include the default value of the parameter.
For example, the following simple class has a method that has a default parameter.
class Person
{ Public void salute( str message = "Hi"){ } }

In this case, the wrapper method must resemble the following example.
[ExtensionOf(classtr(Person))]
final class aPerson_Extension { Public void salute( str message ){ } }
In the aPerson_Extension extension class, notice that the salute method doesn't include the default value of the message parameter.

Wrapping instance and static methods

Instance and static methods can be wrapped by extension classes. If a static method is the target that will be wrapped, the method in the extension must be qualified by using the static keyword.
For example, we have the following A class.
class A { public static void aStaticMethod( int parameter1) { // … } }
In this case, the wrapper method must resemble the following example.
[ExtensionOf(classstr(A)] final class An_Extension { public static void aStaticMethod( int parameter1) { Next aStaticMethod( 10 ); } }

Wrapper methods must always call next

Wrapper methods in an extension class must always call next, so that the next method in the chain and, finally, the original implementation are always called. This restriction helps guarantee that every method in the chain contributes to the result.
In the current implementation of this restriction, the call to next must be in the first-level statements in the method body.
Here are some important rules:
  • Calls to next can't be done conditionally inside an if statement.
  • Calls to next can't be done in whiledo-while, or for loop statements.
  • next statement can't be preceded by a return statement.
  • Because logical expressions are optimized, calls to next can't occur in logical expressions. At runtime, the execution of the complete expression isn't guaranteed.

Wrapping a base method in an extension of a derived class

The following example shows how to wrap a base method in an extension of a derived class. For this example, the following class hierarchy is used.
class A
{ public void salute(str message) { Info(message); } } class B extends A { } class C extends A { }

Therefore, there is one base class, A. Two classes, B and C, are derived from A. We will augment or create an extension class of one of the derived classes (in this case, B), as shown here.
[Extensionof(classstr(B))]
final class aB_Extension { public void salute(str message) { next salute( message ); Info("B extension"); } }

Although the aB_Extension class is an extension of B, and B doesn't have a method definition for the salute method, you can wrap the salute method that is defined in the base class, A. Therefore, only instances of the B class will include the wrapping of the salute method. Instances of the A and Cclasses will never call the wrapper method that is defined in the extension of the B class.
This behavior becomes clearer if we implement a method that uses these three classes.
class ProgramTest
{ Public static void Main( Args _args) { var a = new A( ); var b = new B( ); var c = new C( ); a.salute("Hi"); b.salute("Hi"); c.salute("Hi"); } }
For calls to a.salute(“Hi”) and c.salute(“Hi”), the Infolog shows only the message “Hi.” However, when b.salute(“Hi”) is called, the Infolog shows “Hi” followed by “B extension.”
By using this mechanism, you can wrap the original method only for specific derived classes.

Accessing protected members from extension classes

As of Platform update 9, you can access protected members from extension classes. These protected members include fields and methods. Note that this support isn't specific to wrapping methods but applies all the methods in the class extension. Therefore, class extensions are more powerful than they were before.

The Hookable attribute

If a method is explicitly marked as [Hookable(false)], the method can't be wrapped in an extension class. In the following example, anyMethod can't be wrapped in a class that augments anyClass1.
class anyClass1 { [HookableAttribute(false)] public void anyMethod() {…} }

Final methods and the Wrappable attribute

Public and protected methods that are marked as final can't be wrapped in extension classes. You can override this restriction by using the Wrappable attribute and setting the attribute parameter to true ([Wrappable(true)]). Similarly, to override the default capability for (non-final) public or protected methods, you can mark those methods as non-wrappable ([Wrappable(false)]).
In the following example, the doSomething method is explicitly marked as non-wrappable, even though it's a public method. The doSomethingElse method is explicitly marked as wrappable, even though it's a final method.
class anyClass2 { [Wrappable(false)] public void doSomething(str message) { …} [Wrappable(true)] final public void doSomethingElse(str message){ …} }

Restrictions on wrapper methods

The following sections describe restrictions on the use of CoC and method wrapping.

Kernel methods can't be wrapped

Kernel classes aren't X++ classes. Instead, they are classes that are defined in the kernel of the Microsoft Dynamics 365 Unified Operations platform. Even though extension classes are supported for kernel classes, method wrapping isn't supported for methods of kernel classes. In other words, if you want to wrap a method, the base method must be an X++ method.

X++ classes that are compiled by using Platform update 8 or earlier

The method wrapping feature requires specific functionality that is emitted by an X++ compiler that is part of Platform update 9 or later. Methods that are compiled by using earlier versions don't have the infrastructure to support this feature.

Nested class methods (forms) can't be wrapped

The concept of nested classes in X++ applies to forms for overriding data source methods and form control methods. Methods in nested classes can't be wrapped in class extensions.

Friday, August 3, 2018

Difference between Abstract and Interface

Interface :
An interface is an empty shell. There are only the signatures of the methods, which implies that the methods do not have a body. The interface can't do anything. It's just a pattern.

In X++ an interface is a specification for a set of public instance methods. To create an interface, you begin by using the AOT to create a class. You edit the code of its classDeclaration node to replace the keyword class with the keyword interface. Then you add methods to the interface just as you would for a class, except no code is allowed inside the method bodies.

The purpose of interfaces is to define and enforce similarities between unrelated classes without having to artificially derive one class from the other.
Implements and extends
You can add the implements keyword on a class declaration, and this requires the class to declare the methods that are specified by the interface. A class declaration can implement multiple interfaces by listing them after the single occurrence of the implements keyword, with commas separating the interface names.

An interface can extend another interface by using the extends keyword. An interface cannot extend more than one interface.
Public
All interfaces are public regardless of whether you explicitly write the keyword public in front of the keyword interface in the classDeclaration. The methods on an interface are also public, and again the explicit inclusion of the keyword public is optional.
All interface methods that a class implements must be declared with the explicit keyword public in the class. Also, a class that implements an interface must also be declared with public.

Example :

// I say all motor vehicles should look like this:
interface MotorVehicle
{
    void run();

    int getFuel();
}

// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{

    int fuel;

    void run()
    {
        print("Wrroooooooom");
    }


    int getFuel()
    {
        return this.fuel;
    }
}
Implementing an interface consumes very little CPU, because it's not a class, just a bunch of names, and therefore there isn't any expensive look-up to do. It's great when it matters, such as in embedded devices.


Abstract classes:
Abstract classes, unlike interfaces, are classes. They are more expensive to use, because there is a look-up to do when you inherit from them.
Abstract classes look a lot like interfaces, but they have something more: You can define a behavior for them. It's more about a person saying, "these classes should look like that, and they have that in common, so fill in the blanks!".
For example:
// I say all motor vehicles should look like this:
abstract class MotorVehicle
{

    int fuel;

    // They ALL have fuel, so lets implement this for everybody.
    int getFuel()
    {
         return this.fuel;
    }

    // That can be very different, force them to provide their
    // own implementation.
    abstract void run();
}

// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
    void run()
    {
        print("Wrroooooooom");
    }
}

enter image description here

Source :https://stackoverflow.com/questions/1913098/what-is-the-difference-between-an-interface-and-abstract-class

Source :https://msdn.microsoft.com/en-us/library/aa892319.aspx

Thursday, August 2, 2018

How to use Normal Table as Temp Table?


setTmp() : has nothing to do with deletion at all. It turns a buffer to a temporary one, therefore it saves records to memory/on disk instead of into database. If you delete everything from the temporary buffer, it doesn't delete anything in database, obviously.

So any data manipulations will be lost once the execution of this method is over and actual table content will not be affected.

Will use doInsert() to bypass any validation rules which are not required for temporary table.

As an example, we will use the vendor table to insert and display a couple of temporary
records without affecting actual data.

1. In AOT, create a new class called VendTableTmp with the following code:
class VendTableTmp
{
}
server static void main(Args _args)
{
VendTable vendTable;
;
vendTable.setTmp();
vendTable.AccountNum = ’1000′;
vendTable.Name = ‘Vendor 1′;
vendTable.PartyId = ’1′;
vendTable.doInsert();
vendTable.clear();
vendTable.AccountNum = ’1002′;
vendTable.Name = ‘Vendor 2′;
vendTable.PartyId = ’2′;
vendTable.doInsert();
while select vendTable

{
info(strfmt(
“%1 – %2″,
vendTable.AccountNum,
vendTable.Name));
}
}

2. Run the class to see results:

1000 Vendor 1

1002 Vendor 2

Wednesday, August 1, 2018

Difference between AX 2012 and D 365 Finance and Operations

Apparently in lay man terms we can say the Three main visible changes in D365 :

  • New Client
  • Cloud Readiness
  • New Development Stack
Key terms in D365:

Packages : A package is a deployable unit, which may have multiple modals.

Model:  A model is a group of elements, a model is collection of elements that represent a distributed sofware solution.

Element:  Element is any object residing in AOT.
eg: Base Enum, any EDT, Table, Form which you see in AOT tree in an element itself.  

Project : Project are the logical container for everything thats needed to build your application.
A project can be associated with any one model.

I got some detail understanding on the changes from different blogs, which I am sharing below


Dynamics 365 for Operations is web/browser based, hosted by Microsoft on Azure (like Office 365) is provides similar functionality, but has a completely new UI. It is part of their family called Dynamics 365 that merges elements of Microsoft Dynamics CRM, AX and the financials from Dynamics NAV.

Enhanced User Experience :
  • One of the biggest differences in the new version is in the user experience, as Dynamics 365 for Operations has a new interface . 
  • Also, the entire program is now web-oriented, so everything you need is located within a browser, which should make everything faster and easier to use.
  • The user experience will be enhanced even more by the fact that Microsoft has now made Dynamics 365 compatible with mobile devices like phones and tablets
  • Users having real-time access to data on these devices is a game changer for nearly any company, as it will allow them to do business anywhere and at any time.
More Integrations :

The intelligence of Dynamics 365 is also miles ahead of previous versions. There is now full integration with CRM, Office 365, and PowerBI, not to mention Cortana, so the speed at which you can retrieve data and make accurate and informed decisions is quite impressive.


Changes for Developers :

1. Visual Studio :

MorphX is gone, Visual Studio (VS) is the new IDE. All of Microsoft Dynamics 365 is web-based, there is no longer a fat AX client and there is no MorphX development environment to get into. You will do all of your work in VS. It is well-documented, stable, and feature rich. 

2. Deployment Packages :
  • The next big change is the introduction of deployment packages and the marginalization of the traditional AX concept of layers. Deployment packages are conceptually a replacement for model stores. 

  • Deployment packages are comprised of all of the artifacts (like assemblies and configurations files) required to make the code function. 

  • When moving code between environments, deployment packages will be used. 

  • As part of this change, when you create a model in Visual Studio (VS) you indicate which deployment package the model is a part of and what kind of dependencies it has. Similar to how in VS when you add a reference to a project, you create a dependency between your project and the one you added a reference to. 

  • Additionally, when you create your model, you specify which layer the model is going to live in. The layer is the traditional AX concept of a layer but in the VS world, the layer’s importance is very minimal. You are not required to provide a key for your model to live in that layer.

3. Extensions :
  • Dynamics 365 for Operations includes the introduction of extensions. In all previous versions of AX when modifying or adding to sys or ISV code, you override or added something to an object which created a potential conflict at upgrade time.

  • In Dynamics 365 this is still possible it is known as a customization but now it is not the only way to modify existing code. Microsoft has added an extensions model with extensions you can extend an object without touching the base object. This means you can add new fields, methods or controls to tables, classes and forms and those additions are contained in your own extension object. You have not affected the base object.

  • Also the base objects have many, many events added to them. In previous versions of AX, you override methods so your code would be called when events happened – like a button being clicked. Now the button will raise an event and you can subscribe to that event. By subscribing to the event your code will be called without you having to override or modify the button.

4. Form Patterns :

The required adherence to form patterns are next big change. Form patterns are guidelines Microsoft has for how forms should be designed. Microsoft wants all forms in AX to look-and-feel similar regardless of who makes them so the end user has a consistent experience. Form patterns are not a new concept; they exist in AX 2012. However, most AX developers were not aware of them in AX 2012 because they were a guideline and not a requirement. 

In Dynamics 365 when you create a form, the first thing you do in the design of that form is specify the form pattern it is going to follow. If you don’t specify the form pattern, you will get compile errors. 

As you continue to build the form’s design, the pattern for the form is enforced meaning you must fill out the requirements of the pattern and if you do not you will get compile errors. This definitely takes some time to get used to.

5. Introduction of Data Entities :

Introduction of data entities. Data entities serve as the new framework for integrating with AX. They are a replacement two concepts in AX 2012, document services and the classes that comprised the Data Import Export Framework (DIXF). 

With data entities, all data coming into and going out of AX follow the same path so you do not have to build two different things if you are calling an API or using DIXF to manipulate data. 

The data entities are very easy to create. There is a wizard that walks you through the creation process similar to the wizard in AX 2012 used to generate document services. 

Another notable change within integrations is that the services exposing data entities are restful state APIs using JSON formatted data. 

In AX2012 all services were WCF services. This change means the way you call services is significantly different so if you are planning to do integrations on Dynamics 365 you will want to study up on how to call the APIs.



VS project types:

There are Dynamics AX template project types that have been added to VS.

The template project types are:

Dynamics AX Best Practice Rules – used for writing best practices checks for code and metadata
Dynamics AX Developer Tool Add-in
Dynamics AX Project – main project template type for containing customizations


When creating a new project, first create a new model:

  • If you create a project without a new model, the project gets created in the sys layer in the model where the object being modified exists.
  • Because the project is in the sys layer you cannot add existing objects to the project because you are working in the sys layer.
  • You need to create a new model and put your projects inside of it.

When you create the new model, the dialog asking about the new model will prompt for:
  • The layer you want to work in
  • The package you want to work in
  • The first project you want to create
Once the project has been created you can see the layer and model next to the project name in the Solution Explorer.


AXPP Files

1. Files ending in axpp are the replacement for xpo files.

2. To export and import projects similar to what you would do with xpos on 2012:

In the Solution Explorer, right-click on a project and choose Export project <ProjectName>
The project gets saved as a file with an extension of .axpp

     a. The model the project is created in is saved in the axpp file

            i. The model contains the layer info. 

     b. The axpp file cannot be read with Notepad

3. To import the axpp containing the project in VS go to the Dynamics AX menu and choose Import project.

      a. The project is created in the model (and layer) and saved in the axpp file.

            i. If the model doesn’t exist in the imported environment, it will be generated.

4. Similar to AX 2012 and importing an xpo, in Dynamics 365 for Operations (AX7) you can do a comparison between the contents of the axpp file and the current environment.

      a. To compare objects during the import: When you select Import project a dialog opens asking you to select the location of the axpp file.

  • When you select Import project a dialog opens asking you to select the location of the axpp file.
  • Once you have selected the axpp file at the bottom of the dialog there is a Details section.
  • In the details section, you can see all of the objects to be imported.
  • When viewing the objects, right-click on one of them and choose Compare to bring up compare window.

Packages

  • It includes all of the models, binaries and additional pieces needed to deploy code.
  • Similar concept to an AX2012 modelstore or in VS a solution.
                   You can have multiple packages per installation.
  • AX ships with several packages including:
                   Application Suite - This is the package containing most of the application code and is the most likely to be overridden.

  • Application Suite Form Adaptor
  • Application Foundation
  • Application Foundation Form Adaptor
  • Application Platform
  • Application Platform Form Adaptor
  • When creating a model, the wizard prompts for which package the model should live in.
  • To create customization objects (overlayer objects) you have to:
             Create a new model in the same package as the objects being customized.
                     This is because there will be a dependency between your customizations and the objects being customized.
  • The new model has to exist in a layer that you can access (usr, cus, or var).

How to enable the dimension fields based on the Item selected on the form.

[Form] public class KMTShipFromWarehouses extends FormRun {     InventDimCtrl_Frm_EditDimensions        inventDimFormSetup;     /// ...