Is there a way to get [ Internal, Private ] property?

I have a class defined like this:

Class test.ABC Extends %RegisteredObject   {

Property myProp As %Binary [ Internal, Private ];

}

Is there a way to get a value of myProp from outside of the object?

I can't modify or extend the class obviously.

  • + 1
  • 1
  • 226
  • 7
  • 1

Answers

Hello Eduard,

For debug purpose , you can try this :

Set obj = {Your test.ABC instance}

Set res = ##class(%Studio.General).DumpObjectFunc(obj)

While res.%Next() { Write !,"Property : ",res.%Get("Name"), !," Value : ",res.%Get("Value") }

Or just perform a zw obj

Regards.

Lorenzo.

EDIT : I tested with ##class(%Studio.General).DumpObjectFunc(obj)

We can get value if "myProp" is not an object.

Thank you, ended up extracting this method:

ClassMethod GetPrivateProp(oref, propName) As %String
{
    Set value = ""
    Set cd=$system.CLS.DumpContext(oref,0)
    Set inst=$piece(cd,"^",8)
    For j=1:1:inst {
        Set pd=$system.CLS.Property(j,oref,0)
        Set ivar=$piece(pd,"^")
        CONTINUE:ivar'=propName
        Set slot=$piece(pd,"^",2)
        Set value = $zobjval(oref,slot,0,3,slot)
        Quit
    }
    
    Quit value
}

UPD: Simplified code, thanks to @Dmitry Maslennikov suggestion:

ClassMethod GetPrivateProp(oref, propName) As %String
{
    Set pd=$system.CLS.Property(propName,oref,0)
    Set slot=$piece(pd,"^",2)
    Set value = $zobjval(oref,slot,0,3,slot)
    Quit value
}

I'd like to get an Intersystems expert reference to Eduard's method. Would you encourage us to use such methods (like using $piece etc. to get info from inside objects) Thanks, Uri

I would say that this is definitely not recommended.  It does violate the intent of the object design.  You are probably not privy to why this was marked private and internal.  Providing a method to bypass that could create problems.  Of course if this is only for debugging a class that you don't have the ability to edit it may be acceptable.

Can be easier:

ClassMethod GetPrivateProp(
  oref,
  propNameAs %String
{
  ##class(%Studio.General).DumpObjectExecute(.arr,oref)
  arr(propName)
}

Great!

There, a version with multidimensional array support until 4 subscripts level : 

ClassMethod GetPrivateProp(
   oref,
   propName,
   ByRef result As %Binary) As %String
{
   Do ##class(%Studio.General).DumpObjectExecute(.arr,.oref)
   Set key = $o(arr(propName),1,value), @propName = arr(propName)
   For  {
      Quit:(key="")||($Qs(key,0)'=propName)
      Set subscriptLevel = $Ql(key)
      If subscriptLevel=1 {
         Set @propName@($Qs(key,1))=value
      }ElseIf subscriptLevel=2 {
         Set @propName@($Qs(key,1),$Qs(key,2))=value
      }ElseIf subscriptLevel=3 {
         Set @propName@($Qs(key,1),$Qs(key,2),$Qs(key,3))=value
      }ElseIf subscriptLevel=4 {
         Set @propName@($Qs(key,1),$Qs(key,2),$Qs(key,3),$Qs(key,4))=value
      }
      Set key = $o(arr(key),1,value)
   }
   Merge result=@propName
   Kill @propName
   Quit:$Quit arr(propName) Quit
}

$system.CLS.Property accepts property by name as well, so you don't need loop