Some thoughts.

1. Do not use Hungarian notation.

2. Do not use ByRef params/dynamic objects/$lists/args... as an arguments. There are two exceptions:  you don't know the number of arguments or there's more than 10 arguments.

3. Method should not parse arguments, only validate arguments. If caller passed invalid input it's caller problem. Fail fast.

4. Mandatory arguments go first.

5. If several methods have similar signatures, the order of arguments should be the same.

6. Same logical arguments in different methods should have the same names.

7. Arguments should be consistent. If you pass primitives, pass primitives everywhere. If you pass dynamic objects, pass them everywhere.

8. Return types should also be consistent.

9. If it's object methods and you pass the same optional arguments in several methods extract these arguments as a property.
 

You can do it with a special property class. Here's how it works:

Class Testing.PropertyClass
{
Parameter myPropName;
}

Class Testing.MyPersistentClass Extends %RegisteredObject  [ PropertyClass = Testing.PropertyClass]
{
Property p1 As %String(MAXLEN = 5, myPropName = "myPropValue");
}

But I recommend you to check RESTForms project (part1, part2), which sounds like what you're doing -automatic REST interface for persistent  classes.

It also defines property class for similar purposes.

Why do you want to achieve that?

You need custom datatype for that, defining your parameters:

Class Testing.String Extends %String
{
Parameter myPropName;
}

And use that as a property type:

Class Testing.PropertyParameters Extends %RegisteredObject
{
Property p1 As Testing.String(MAXLEN = 5, myPropName = "myPropValue");
}

Still, please tell us your use case.

You can also write a stored procedure which accepts id and returns the field you need.

Here's an example:

ClassMethod ListProp(id, prop, listprop) As %String [ SqlProc ]
{
    set ids = $classmethod(, prop _ "GetStored", id)
    quit:'$lv(ids) ""
    
    set ptr = 0
    set result = ""
    if listprop="id" {
        while $listnext(ids, ptr, value) {
            set result = result _ value
        }    
    } else {
        set propClass = $$$defMemberKeyGet($classname(),$$$cCLASSproperty,prop,$$$cPROPtype)
        while $listnext(ids, ptr, value) {
            set result = result _ $lb($classmethod(propClass, listprop _ "GetStored", $lg(value)))
        }
    }
    
    quit $lts(result)
}

Arguments:

  • id - root object id
  • prop - name of "List Of" property (in your case - Collection)
  • listprop - name of element property (in your case  name of any property from ICT.Experiments.B class)

Check out our webinar today! It would be about Python Gateway/ML.
Also, there's ML Toolkit user group - a private GitHub repository set up as part of InterSystems corporate GitHub organization. It is addressed to the external users that are installing, learning or are already using ML Toolkit components. To join ML Toolkit user group, please send a short e-mail at the following address: MLToolkit@intersystems.com and indicate in your e-mail the following details (needed for the group members to get to know and identify you during discussions):

  • GitHub username
  • Full Name (your first name followed by your last name in Latin script)
  • Organization (you are working for, or you study at, or your home office)
  • Position (your actual position in your organization, or “Student”, or “Independent”)
  • Country (you are based in)

Working code:

int GetGlobalOrder(char *global, int start, int end, CACHE_EXSTRP result)
{
    if (isInitialized == false) {
        Initialize(NULL);
    }

    // narg Number of subscript expressions pushed onto the argument stack.
    int narg = 1;

    // Direction for the $Order is 1 for forward, -1 for reverse.
    int dir = 1;
    // Indicates whether the data value, if there is one, should be returned.
    int valueflag = 1;

    // Has argument flag
    int flag = 0;

    // key - current subscript
    int key = start - 1;
    
    // row count
    int c=0;

    while (key<end) {
        CACHEPUSHGLOBAL(strlen(global), global);
        CACHEPUSHINT(key);
        CACHEGLOBALORDER(narg,  dir, valueflag);

        CACHEPOPINT(&flag);
        if (flag) {
          //use CACHETYPE() to get the value type, then the appropriate CACHEPOP for the subscript
          CACHEEXSTRKILL(result);
          CACHEPOPEXSTR(result);
          // do stuff with result
        }
        //use CACHETYPE() to get the subscript type, then the appropriate CACHEPOP for the subscript
        int type = CACHETYPE();

        CACHEPOPINT(&key);

        if (key==NULL) {
            break;
        }

        c++;
    }
    return ZF_SUCCESS;
}

Thanks to  @Chuck Sorenson for help!