0

I want to add a method dynamically to a component in ax 2012, how can I do this through code? Is it possible?

Jan B. Kjeldsen
  • 17,817
  • 5
  • 32
  • 50
user3226663
  • 137
  • 3
  • 17
  • Not sure what you mean by "component" or what you are actually trying to accomplish, but did you take a look at the event handling possibilities in AX 2012 (https://msdn.microsoft.com/en-us/library/gg839762.aspx)? – FH-Inway Apr 24 '15 at 08:32
  • Actually the component here refers to class or table or form or map. I need to add a method dynamically like public static str getTime(){ ret "time "; } – user3226663 Apr 24 '15 at 08:56
  • Component here refers to a Class or Map or Table or Form in the AOT, I need to check if the method named getTime() like public static str getTime(){ret "3/3/2015";} exists in the component if not found then create the above method in that component. for Eg: we have class in the AOT named ImageListAppl, i need to check whether method named getTime() exists or not, if not found then create getTime() method dynamically in that class. this is same for other components also like tables, maps,forms. – user3226663 Apr 24 '15 at 09:02
  • Take a look at class `ClassBuild`, this should give you some ideas. When I find the time, I will write up an answer with some example code. – FH-Inway Apr 24 '15 at 14:25

2 Answers2

3

Here is a job I wrote that demonstrates a bunch of different ways of doing what you're wanting:

static void Job79(Args _args)
{
    TreeNode        treeNode = TreeNode::findNode(@'\Classes\Activities');
    SysDictClass    sysDictClass = new SysDictClass(treeNode.applObjectId());
    FormRun         formRun = new FormRun(new Args(formStr(AifAction)));
    Form            form = new Form(formStr(AifAction));
    ClassBuild      classBuild;
    SysDictTable    sysDictTable = new SysDictTable(tableNum(AccountSumMap)); // Maps are treated like tables
    SysDictMethod   sysDictMethod;
    int             i;
    MemberFunction  method;
    str             methodSource = 'public static str getTime()\n{\n\treturn "3/3/2015";\n}';


    // Find if class has a method
    if (sysDictClass.hasObjectMethod('delete'))
    {
        info("Found object method delete");
    }

    if (sysDictClass.hasStaticMethod('main'))
    {
        info("Found static method main");
    }

    // Find if form has a method
    if (formHasMethod(formRun, 'init'))
    {
        info("Found form method 'init'");
    }


    if (form.AOTfindChild('methods').AOTfindChild('refreshGrid') != null)
    {
        info("Found 'refreshGrid' method on AifAction");
    }


    if (sysDictClass.hasStaticMethod('getTime') == false)
    {
        classBuild = new ClassBuild(sysDictClass.name());

        treeNode = classBuild.addMethod('getTime', methodSource);

        if (classBuild.classNode().AOTcompile())
        {
            classBuild.classNode().AOTsave();
            info("Added method getTime, compiled, and saved");
        }
        else
        {
            info(strFmt("Unable to compile method 'getTime' with source code '%1', restoring class...", treeNode.AOTgetSource()));
            // Delete the non-compiling method
            if (treeNode)
                treeNode.AOTdelete();

            classBuild.classNode().AOTsave();
        }

    }
    else
    {
        info("Method 'getTime' already exists");
    }

    if (sysDictTable.isMap())
    {
        if (sysDictTable.doesMethodExist('getTime') == false)
        {
            treeNode = sysDictTable.treeNode().AOTfindChild('methods').AOTadd('getTime');
            method = sysDictTable.treeNode().AOTfindChild('methods').AOTfindChild('getTime');
            method.AOTsave();
            method.AOTsetSource(methodSource, true);
            method.AOTsave();


            if (sysDictTable.treeNode().AOTcompile())
            {
                sysDictTable.treeNode().AOTsave();
                info(strFmt("Added 'getTime' to AccountSumMap"));
            }
            else
            {
                info(strFmt("Unable to compile method 'getTime' with source code '%1', restoring class...", treeNode.AOTgetSource()));

                // Delete the non-compiling method
                if (treeNode)
                    treeNode.AOTdelete();

                sysDictTable.treeNode().AOTsave();
            }
        }
    }
}
Alex Kwitny
  • 11,211
  • 2
  • 49
  • 71
1
private void findOrCreateTimeStamp(
        SysVersionControlTmpItem                _item)
{
    str                             timeStamp;
    UtilElements                    utilElement;
    SysDictClass                    dictClass;
    ClassBuild                      classBuild;
    SysVersionControlTmpItem        item            = _item;
    str                             methodName      = "csGetVersion";
    int                             time            = timenow();
    TreeNode                        treeNode        = TreeNode::findNode(item.ItemPath);

    utilElement = treeNode.utilElement();            

    timeStamp   = date2Str(
                        today(),
                        321,
                        DateDay::Digits2,
                        DateSeparator::Slash, 
                        DateMonth::Digits2,
                        DateSeparator::Slash,
                        DateYear::Digits4,
                        DateFlags::None);

    timeStamp   = timeStamp + "_"                                           +
                        num2str0(time div 3600, 2, 0, 0, 0) + "_"           +
                        num2Str0(time mod 3600 div 60, 2, 0, 0, 0) + "_"    +
                        num2Str0(time mod 3600 mod 60, 2, 0, 0, 0);

    if (utilElement.recordType == UtilElementType::Class)
    {
        dictClass   = new SysDictClass(className2Id(utilElement.name));
        classBuild  = new ClassBuild(utilElement.name, true);

        if (dictClass.hasStaticMethod(methodName))
        {
            //Override method here, since the method already exists in the component.
            classBuild.overrideMethod(methodName,
                                        @"public static str csGetVersion()" +
                                        "{"                                 +
                                            "return '" + timeStamp + "';"   +
                                        "}"); 
        }
        else
        {
            //Make a new method here since it does'nt exist in the component.
            classBuild.addMethod(methodName,
                                        @"public static str csGetVersion()" +
                                        "{"                                 +
                                            "return '" + timeStamp + "';"   +
                                        "}"); 
        }

        classBuild.classNode().AOTcompile();    
    }
}

The above method is created by referring to previous answer and other professionals. It validates if the method exists in the class first. If found it overrides else creates new method. For other elements like Tables, Forms and Maps we can implement in the similar way.

user3226663
  • 137
  • 3
  • 17