【问题标题】:Add a method dynamically in ax 2012 component在 ax 2012 组件中动态添加方法
【发布时间】:2023-08-13 23:50:02
【问题描述】:

我想在 ax 2012 中为组件动态添加一个方法,我该如何通过代码做到这一点?有可能吗?

【问题讨论】:

  • 不确定您所说的“组件”是什么意思,或者您实际上想要完成什么,但您是否了解过 AX 2012 (msdn.microsoft.com/en-us/library/gg839762.aspx) 中的事件处理可能性?
  • 这里的组件其实是指类或表或表单或映射。我需要动态添加一个方法,比如 public static str getTime(){ ret "time"; }
  • 这里的组件是指AOT中的Class或Map或Table或Form,我需要检查名为getTime()的方法是否像public static str getTime(){ret "3/3/2015 ";} 如果未找到,则存在于组件中,则在该组件中创建上述方法。例如:我们在 AOT 中有一个名为 ImageListAppl 的类,我需要检查名为 getTime() 的方法是否存在,如果没有找到,则在该类中动态创建 getTime() 方法。其他组件也一样,例如表格、地图、表格。
  • 看看ClassBuild类,这应该会给你一些想法。当我找到时间时,我会用一些示例代码写一个答案。

标签: axapta dynamics-ax-2012 dynamics-ax-2012-r2 dynamic-method


【解决方案1】:

这是我写的一份工作,展示了许多不同的方式来做你想做的事:

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();
            }
        }
    }
}

【讨论】:

    【解决方案2】:
    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();    
        }
    }
    

    以上方法是参考之前的回答和其他专业人士创建的。它首先验证该方法是否存在于类中。如果找到它会覆盖 else 创建新方法。对于表格、表格和地图等其他元素,我们可以以类似的方式实现。

    【讨论】: