web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

News and Announcements icon
Community site session details

Community site session details

Session Id :
Microsoft Dynamics AX (Archived)

Dynamically passing multiple parameters to DictClass.callObject method

(0) ShareShare
ReportReport
Posted on by 25

What I am trying to achieve is to dynamically retrieve the class name, method name, and parameter data needed for the method call and pass those parameters into the DictClass.callObject method.

The part that is giving me a problem is the 3rd parameter for the callObject method, (...).  Because the methods that can be called can vary in the number of parameters passed to them, i need to find a way to pass a single variable to this parameter in callObject and have it able to parse it and place the parameters in the correct sequence.  I have tryed passing Lists, Arrays and containers as the parameter, but the result seen is either no data passed to the parameters in the method called, or the first element in the container is placed in the first parameter of the method and all subsequent parameters are blank.

 Any one have any ideas as to work around this problem?  I can provide a sample of code if needed.

 Thanks,

Chris

*This post is locked for comments

I have the same question (0)
  • MohammedRasheed Profile Picture
    1,405 on at
     Hey Chris,

    Totally connect with you man.. I faced the same problem a while ago..

    Its quite frustrating cause I wrote this really neat code... every extensible and got stuck at callObject..

    Unfortunately reflections in x++ are not as powerful as they are in some of the other platforms..

    The problem with call object is that it basically takes one parameter at a time and assigns it to the corresponding parameter on the called method.. there are no enumerators hence the mapping is 1:1.

    There are 2 ways to get around this problem:

    1.       Dynamic code: you will have to use treenode or other editor scripts to write code.. this way will be able to dynamically code the number of parameters required and call the object method..

    The down side is that you will be writing code while users are online... this could have a bad impact in a multi aos environment... also it could prove tricky to handle multiple threads.

    2.       The option that I went for (not very elegant.. but safer) was to assign individual parameters and call CallObject on the basis of a switch case...depending on the requirement, it might work for you.

    I wrote some code to help you out..

     static void DictClassTest(Args _args)
    {
        DictClass           dictClass;
        anytype             retVal;
        str                 resultOutput;
        ExecutePermission   perm;
        container           parmCon;    str                 parmRet;
        int                 conL;
        anytype             parm1;
        anytype             parm2;
        anytype             parm3;
        anytype             parm4; // and so on..
        DictMethod          dictMethod;
        int                 methodId;
        moTestClass         moTestClass;    //treeNode  tn;
        //utilElements ut;
        //xRef rf;
        //struct ss;
        void setParm(Container _con)
        {
            parm1 = conpeek(_con,1);
            parm2 = conpeek(_con,2);
            parm3 = conpeek(_con,3);
            parm4 = conpeek(_con,4);
            // and so on..
        }


        anytype callMethod(container _parmContainer, DictClass _dictClass,Object _Obj,str _methodName)
        {

            setParm(_parmContainer);

            for(methodId = 1;methodId <= _dictClass.objectMethodCnt();methodId++)
            {

                if(_dictClass.objectMethod(methodId) == _methodName)
                {
                    dictMethod =_dictClass.objectMethodObject(methodId);

                    switch(dictMethod.parameterCnt())
                    {
                        Case 0:
                            return _dictClass.callObject(_methodName,_obj);
                        Case 1:
                            return _dictClass.callObject(_methodName,_obj,parm1);
                        Case 2:
                            return _dictClass.callObject(_methodName,_obj,parm1,parm2);
                        Case 3:
                            return _dictClass.callObject(_methodName,_obj,parm1,parm2,parm3);
                        Case 4:
                            return _dictClass.callObject(_methodName,_obj,parm1,parm2,parm4);
                        Default:
                            return _dictClass.callObject(_methodName,_obj); // or null
                    }

                }

            }

        }

        ;

        perm = new ExecutePermission();


        perm.assert();

        // Add some elements to the conainer
        parmCon= conIns(["string",str2date("29/05/2008",-1),34],1);

        moTestClass = new moTestClass();

        dictClass = new DictClass(classidget(moTestClass));

        if (dictClass != null)
        {
            retVal       = callMethod(parmCon,dictClass,moTestClass,"setDateStrInt");
            resultOutput = strfmt("Return value is %1", retVal);
            info(resultOutput);
        }

        // Closes the code access permission scope.
        CodeAccessPermission::revertAssert();

    }

     

    I understand that this would not be the best of solutions... but I could not think of another way around it..

    Hope this helps. Let us know if you have any more questions.

    Regards,

    Mohammed Rasheed

    www.dynamic-ax.co.uk

     

  • Community Member Profile Picture
    on at

    Hi Chris and Mohammed,

    Could this be a good opportunity to use "RunBuf"? Build the call to "CallObject" as a string with the parameters you need, then pass it to RunBuf. What do you think? --Tom

  • MohammedRasheed Profile Picture
    1,405 on at

    Hey Tom, Chris,

    Tom, thanks for your suggestion..

    that is a really good idea.... but I am not sure if it would satisfy requirement..

    runAS could be another option worth considering... but its constrained to code running on the server (and methods that accept and return containers).

    static void main(args _args)
    {
        RunAsPermission     perm;
        container           parmCon;
        container           retCon;
        ;

        perm = new RunAsPermission(curUserId());
        perm.assert();

        parmCon= conIns(["string",str2date("29/05/2008",-1),34],1);

        retCon = RunAs(curUserId(), classnum(moTestClass),"setDateStrInt2",parmCon);

        CodeAccessPermission::revertAssert();
    }

    Chris, let us know if you need any more help. i must say Toms suggestion really sounds good to me.. RunBuf would be a good path to take.

    regards,

    Mohammed Rasheed

    www.dynamic-ax.co.uk

     

  • Chris Jones - ICS Profile Picture
    25 on at

    Hey Tom, Mohammed,

    RunBuf seems to be the way to go.  However, it is much simplier than creating the callObject call within the RunBuf method.  Basically what i did is as follows: 

    <BEGIN CODE>
    str ClassName;
    str MethodName;
    Container Parameters;
    ;

    /*
    <Code to fill above variables>
    */

    new ExecutePermission.assert();

    Parameters = RunBuf(strfmt("Container RunClassMethod(){; return new %1().%2(%3);}",
                                    ClassName,
                                    MethodName,
                                    con2str(Parameters)));

    CodeAccessPermission::revertAssert();
    <END CODE>

     

    You know, I had glanced at RunBuf, but didnt really consider it.  Thanks for bringing it back into the spotlight, as it seems to be exactly what is needed.

    Thanks again.
    Chris

  • Suggested answer
    Sagnik Majumder Profile Picture
    792 on at

    I agree with Mohammad Rasheed.

    I have also written my code similar to this:-

                if (dictClass != null)
                {
                    if(isList)
                    {
                        returnList = dictClass.callObject(_methodname, object,argsArray);
                    }
                    else
                    {
                        switch (argsArray.lastIndex())
                        {
                            case 0:
                                returnList = dictClass.callObject(_methodname, object);
                                break;
                            case 1:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1));
                                break;
                            case 2:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2));
                                break;
                            case 3:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3));
                                break;
                            case 4:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4));
                                break;
                            case 5:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5));
                                break;
                            case 6:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6));
                                break;
                            case 7:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6),argsArray.value(7));
                                break;
                            case 8:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6),argsArray.value(7),argsArray.value(8));
                                break;
                            case 9:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6),argsArray.value(7),argsArray.value(8),argsArray.value(9));
                                break;
                            case 10:
                                returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6),argsArray.value(7),argsArray.value(8),argsArray.value(9),argsArray.value(10));
                                break;
                            default :
                                throw error('Method does not support more than 10 parameter');
                                //... Continue this pattern for the number of parameters you need to support.
                        }
                    }
                }


    Try this. It will solve your issue.

    if (dictClass != null)            {                if(isList)                {                    returnList = dictClass.callObject(_methodname, object,argsArray);                }                else                {                    switch (argsArray.lastIndex())                    {                        case 0:                            returnList = dictClass.callObject(_methodname, object);                            break;                        case 1:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1));                            break;                        case 2:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2));                            break;                        case 3:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3));                            break;                        case 4:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4));                            break;                        case 5:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5));                            break;                        case 6:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6));                            break;                        case 7:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6),argsArray.value(7));                            break;                        case 8:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6),argsArray.value(7),argsArray.value(8));                            break;                        case 9:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6),argsArray.value(7),argsArray.value(8),argsArray.value(9));                            break;                        case 10:                            returnList = dictClass.callObject(_methodname, object, argsArray.value(1),argsArray.value(2),argsArray.value(3),argsArray.value(4),argsArray.value(5),argsArray.value(6),argsArray.value(7),argsArray.value(8),argsArray.value(9),argsArray.value(10));                            break;                        default :                            throw error('Method does not support more than 10 parameter');                            //... Continue this pattern for the number of parameters you need to support.                    }                }            }

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Season of Sharing Community Challenge Launch!

Jump in, show your community spirit, and win prizes!

Women in Power Builds Momentum

Expanding mentorship, skilling, and AI innovation

Congratulations to the April Top 10 Community Leaders

These are the community rock stars!

Leaderboard > 🔒一 Microsoft Dynamics AX (Archived)

#1
CP04-islander Profile Picture

CP04-islander 21

#2
dekion Profile Picture

dekion 4

#2
Virginia99 Profile Picture

Virginia99 4

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans