Written by

Senior Cloud Architect at InterSystems
Question Eduard Lebedyuk · May 17, 2019

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.

Comments

Lorenzo Scalese · May 18, 2019

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.

0
Eduard Lebedyuk  May 21, 2019 to Lorenzo Scalese

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
}
0
Uri Shmueli  May 21, 2019 to Eduard Lebedyuk

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

0
Eduard Lebedyuk  May 21, 2019 to Uri Shmueli

That's definitely not a recommended practice.

0
Rich Taylor  May 21, 2019 to Uri Shmueli

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.

0
Lorenzo Scalese  May 21, 2019 to Vitaliy Serdtsev

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}
0
Vitaliy Serdtsev  May 21, 2019 to Eduard Lebedyuk

Can be easier:

<FONT COLOR="#000080">ClassMethod </FONT><FONT COLOR="#000000">GetPrivateProp(
  </FONT><FONT COLOR="#ff00ff">oref</FONT><FONT COLOR="#000000">,
  </FONT><FONT COLOR="#ff00ff">propName</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#000080">As %String
</FONT><FONT COLOR="#000000">{
  </FONT><FONT COLOR="#0000ff">d </FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%Studio.General</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">DumpObjectExecute</FONT><FONT COLOR="#000000">(.</FONT><FONT COLOR="#800000">arr</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">oref</FONT><FONT COLOR="#000000">)
  </FONT><FONT COLOR="#0000ff">q </FONT><FONT COLOR="#800000">arr</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">propName</FONT><FONT COLOR="#000000">)
}</FONT>
0
Dmitry Maslennikov  May 21, 2019 to Eduard Lebedyuk

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

0