In PowerBuilder 12 Classic, I am trying to dynamically access/set the properties/elements of a structure. Any idea how to do this?
I开发者_运维知识库'm attempting to build a developer utility which will examine an arbitrary structure (one which is unknown at compile time) to find its elements. This I can get the names and types of the elements by accessing the VariableList
property of the structure's ClassDefinition
. But knowing the name and type of the element doesn't help me, as I know no way to access the elements by name.
For example, say I have a structure st_person
with two string elements: first_name
and last_name
. Is there a way to express setting the value? Anything remotely like this:
st_person l_person
Any myStructure
myStructure = l_person
myStructure.setValue("first_name") = 'John'
myStructure.setValue("last_name") = 'Smith'
I really hope I'm not missing something obvious.
No, you're not missing anything, unless you program in PBNI. From what I've heard of PBNI, you should be able to do this, but I'm not a reliable source of information about PBNI.
Is there a reason why you're using a structure? It sounds like what you want is close to a hash table or a named item set. I've built my own named item set on top of one of PFC's linked lists, where in each node the key is the name, and the data is... well, the data. Very roughly, I have an of_get (string as_name) returns any, and of_set (string as_name, any aa_value). That way, I can
myList = CREATE n_cst_NamedItemSet
myList.of_Set ("first_name", "John")
myList.of_Set ("last_name", "Smith")
and on the other end that receives this (this is great for OpenWithParm and other things that expect one parameter)
is_FirstName = of_Get ("first_name")
is_LastName = of_Get ("last_name")
Going a step further, I have of_Defined (string as_name) to test for existence and of_Get (string as_name, ref any aa_value) returns integer that returns success if found, to enable things like optional parameters and looser contracts between objects.
There's more, but that should get you going. If you're not using PFC and you don't feel like carving the linked lists out of it, there's probably no reason you can't build this on top of a pair of parallel unbounded arrays: one String for keys and one Any for data. Or, substitute a DataStore with a String key column (DataStore makes searching for keys quicker) and a Number column as an index into an unbounded Any array.
Good luck,
Terry.
I'm adding another answer to respond to Hugh's new target (his comment on May 20/2011) of converting strings to enumerated values. I've got code that generates code that converts strings to enumerated and enumerated to strings, done in PFC style (like n_cst_conversion). The only thing you have to do to adapt to your version of PowerBuilder is, in the Constructor, update the list of enumerated classifications. (I usually get this from a report from PB's object browser, run through some regular text search and replace.) It's not perfect, but it gets you by until the next time you do a major upgrade.
Good luck,
Terry.
n_cst_enumscripts
InstanceVariables
string is_EnumTypes[]
event constructor returns long
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "accessiblerole"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "alignment"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "argcallingconvention"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "arrangeopen"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "arrangetypes"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "band"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "border"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "borderstyle"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "button"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "charset"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "clipboardformat"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "connectprivilege"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "converttype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "cputypes"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "datetimeformat"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "dbnotification"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "direction"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "displaysizemode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "dragmodes"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "dwbuffer"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "dwconflictresolution"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "dwitemstatus"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "encoding"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "errorreturn"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "exceptionaction"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "fileaccess"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "filelock"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "filemode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "filetype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "fillpattern"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "fontcharset"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "fontfamily"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "fontpitch"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "graxisdatatype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grcolortype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grdatatype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grgraphtype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grlegendtype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grobjecttype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grresettype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grroundtotype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grscaletype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grscalevalue"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grsorttype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grsymboltype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "grtictype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "helpcommand"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "htickmarks"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "icon"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "inkcollectionmode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "inkcompressionmode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "inkeditstatus"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "inkmode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "inkpentip"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "inkpersistenceformat"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "inkpiceditmode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "inkpicstatus"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "keycode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "languageid"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "languagesortid"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "libdirtype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "libexporttype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "libimporttype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "linestyle"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "listviewview"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "location"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "mailfiletype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "maillogonoption"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "mailreadoption"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "mailrecipienttype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "mailreturncode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "maskdatatype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "menuitemtype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "menumergeoption"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "menustyle"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "metadatatype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "moncaldisplaystate"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "moncalrepeattype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "object"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "olefunctioncalltype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "omactivatetype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "omactivation"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "omcontentsallowed"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "omdisplaytype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "omlinkupdateoptions"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "orientationtype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "ostypes"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "paragraphsetting"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "parmtype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "pbtypes"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "pdfmethod"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "pointer"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "profileroutinekind"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "registryvaluetype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "richtexttoolbaractivation"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "rowfocusind"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "saveastype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "savemetadata"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "scriptkind"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "seektype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "setpostype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "sizemode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "spacing"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "sqlfunction"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "sqlpreviewfunction"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "sqlpreviewtype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "stgreadmode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "stgsharemode"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "syncprocesstype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "tabposition"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "textcase"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "textstyle"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "timerkind"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "toolbaralignment"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "toolbarstyle"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "traceactivity"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "tracecategory"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "treenavigation"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "trigevent"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "typecategory"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "userobjects"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "valschemetype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "varaccess"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "variablecardinalitytype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "variablekind"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "vtextalign"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "vtickmarks"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "webpagingmethod"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "weekday"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "windowanimationstyle"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "windowstate"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "windowtype"
is_EnumTypes[UpperBound (is_EnumTypes) + 1] = "writemode"
*function of_enumprototypes () returns string*
integer li_EnumCount, li_Enum
string ls_Prototypes
TypeDefinition ltd_Enum
EnumerationDefinition led_Enum
ls_Prototypes = "Add this list to the forward prototypes section of pfc_n_cst_conversion~r~n~r~n"
li_EnumCount = UpperBound (is_EnumTypes)
FOR li_Enum = 1 TO li_EnumCount
ls_Prototypes += "public function string of_string (" + is_EnumTypes[li_Enum] + " aenum_Value)~r~n"
NEXT
FOR li_Enum = 1 TO li_EnumCount
ls_Prototypes += "public function integer of_" + is_EnumTypes[li_Enum] + " (string as_Value, " + is_EnumTypes[li_Enum] + " ae_Value)~r~n"
NEXT
ls_Prototypes += "~r~n~r~n"
RETURN ls_Prototypes
*function of_enumscripts () returns string*
integer li_EnumCount, li_Enum, li_ValueCount, li_Value
string ls_Scripts, ls_Name
TypeDefinition ltd_Enum
EnumerationDefinition led_Enum
li_EnumCount = UpperBound (is_EnumTypes)
FOR li_Enum = 1 TO li_EnumCount
ltd_Enum = FindTypeDefinition (is_EnumTypes[li_Enum])
led_Enum = ltd_Enum
ls_Scripts += "public function string of_string (" + is_EnumTypes[li_Enum] + &
" aenum_Value);//////////////////////////////////////////////////////////////////////////////~r~n" + &
"//~r~n" + &
"//~tFunction:~t~tof_String~r~n" + &
"//~r~n" + &
"//~tAccess:~t~t~tpublic~r~n" + &
"//~r~n" + &
"//~tArguments:~r~n" + &
"//~tae_icon~t~t~tThe " + is_EnumTypes[li_Enum] +" value to be converted to a string.~r~n" + &
"//~r~n" + &
"//~tReturns: ~t~tstring~r~n" + &
"//~t~t~t~t~t~tA string representation of the " + is_EnumTypes[li_Enum] + " value.~r~n" + &
"//~t~t~t~t~t~tIf aenum_Value is NULL, the function returns NULL.~r~n" + &
"//~t~t~t~t~t~tIf aenum_Value is Invalid, the function returns '!'.~r~n" + &
"//~r~n" + &
"//~tDescription:~tConverts the " + is_EnumTypes[li_Enum] + " enumerated datatype to a~r~n" + &
"//~t~t~t~t~t~treadable string representation.~r~n" + &
"//~r~n" + &
"//////////////////////////////////////////////////////////////////////////////~r~n" + &
"string ls_Null~r~n~r~n// Check parameter~r~nIF IsNull (aenum_Value) THEN~r~n~tSetNull (ls_Null)~r~n~tRETURN ls_Null~r~nEND IF~r~n~r~n"
ls_Scripts += "CHOOSE CASE aenum_Value~r~n"
li_ValueCount = UpperBound (led_Enum.Enumeration)
FOR li_Value = 1 TO li_ValueCount
ls_Name = led_Enum.Enumeration[li_Value].Name
ls_Scripts += "~r~n~tCASE " + ls_Name + "!;RETURN ~"" + ls_Name + "~"~r~n"
NEXT
ls_Scripts += "~r~nEND CHOOSE~r~n~r~n// Invalid parameter~r~nRETURN ~"!~"~r~nend function~r~n~r~n"
NEXT
FOR li_Enum = 1 TO li_EnumCount
ltd_Enum = FindTypeDefinition (is_EnumTypes[li_Enum])
led_Enum = ltd_Enum
ls_Scripts += "public function integer of_" + is_EnumTypes[li_Enum] + &
" (string as_Value, " + is_EnumTypes[li_Enum] + " ae_Value);//////////////////////////////////////////////////////////////////////////////~r~n" + &
"//~r~n" + &
"//~tFunction: ~t~tof_" + is_EnumTypes[li_Enum] + "~r~n" + &
"//~r~n" + &
"//~tAccess: ~t~tpublic~r~n" + &
"//~r~n" + &
"//~tArguments:~r~n" + &
"//~tas_Value~t~t~tThe string value to be converted to " + is_EnumTypes[li_Enum] + " datatype value.~r~n" + &
"//~tae_Value~t~t~tA " + is_EnumTypes[li_Enum] + " variable passed by reference which will~r~n" + &
"//~t~t~t~t~t~t~thold the " + is_EnumTypes[li_Enum] + " value that the string value was~r~n" + &
"//~t~t~t~t~t~t~tconverted to.~r~n" + &
"//~r~n" + &
"//~tReturns: ~t~tinteger~r~n" + &
"//~t~t~t~t~t~t1 if a successful conversion was made.~r~n" + &
"//~t~t~t~t~t~tIf as_Value value is NULL, function returns -1~r~n" + &
"//~t~t~t~t~t~tIf as_Value value is Invalid, function returns -1~r~n" + &
"//~r~n" + &
"//~tDescription: Converts a string value to a " + is_EnumTypes[li_Enum] + " data type value.~r~n" + &
"//~r~n" + &
"//////////////////////////////////////////////////////////////////////////////~r~n" + &
"//~r~n" + &
"//~tRevision History~r~n" + &
"//~r~n" + &
"//~tPFC OS Issues~r~n" + &
"//~t6~tAuto-generated intial version~r~n" + &
"//~t~tTerry Voth: http://www.techno-kitten.com~r~n" + &
"//~r~n" + &
"//////////////////////////////////////////////////////////////////////////////~r~n" + &
"//~r~n" + &
"//~tCopyright © 1996-1997 Sybase, Inc. and its subsidiaries. All rights reserved.~r~n" + &
"//~tAny distribution of the PowerBuilder Foundation Classes (PFC)~r~n" + &
"//~tsource code by other than Sybase, Inc. and its subsidiaries is prohibited.~r~n" + &
"//~r~n" + &
"//////////////////////////////////////////////////////////////////////////////~r~n" + &
"as_Value = Lower (as_Value)~r~n~r~n// Check parameter~r~nIF IsNull (as_Value) THEN~r~n~tRETURN -1~r~nEND IF~r~n~r~n"
ls_Scripts += "CHOOSE CASE as_Value~r~n"
li_ValueCount = UpperBound (led_Enum.Enumeration)
FOR li_Value = 1 TO li_ValueCount
ls_Name = led_Enum.Enumeration[li_Value].Name
ls_Scripts += "~r~n~tCASE ~"" + ls_Name + "~", ~"" + ls_Name + "!~"~r~n~t~tae_Value = " + ls_Name + "!~r~n~t~tRETURN 1~r~n"
NEXT
ls_Scripts += "~r~nEND CHOOSE~r~n~r~n// Invalid parameter~r~nRETURN -1~r~nend function~r~n~r~n"
NEXT
RETURN ls_Scripts
精彩评论