AutoIt-Object -- dynamische Wertezuweisung an Properties

    • Offizieller Beitrag

    Hi,
    hat schonmal jemand mit AutoIt-Object und dynamischen Properties gearbeitet?
    Ich erstelle ein Objekt mit unterschiedlicher Anzahl an Properties. Die Property-Namen werden beim Erstellen übergeben und auch im Objekt als Array hinterlegt.
    Wenn ich dann mit dem Objekt arbeite, möchte ich auch in einem Rutsch alle Werte der Properties ändern können. Also Abarbeiten in einer Schleife.
    Beim Auslesen kann man das mit Execute hinbiegen - aber wie kann ich das bei Wertzuweisungen erledigen?

    Bsp.-Skript

    Spoiler anzeigen
    [autoit]


    #include "AutoitObject.au3"
    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    _AutoItObject_StartUp()

    [/autoit] [autoit][/autoit] [autoit]

    ; Objekt mit Properties erstellen
    $o = _Obj('Alpha;Beta;Gamma;Delta')

    [/autoit] [autoit][/autoit] [autoit]

    ; Property-Namen anzeigen
    $aProps = $o.ArrayProps
    _ArrayDisplay($aProps)

    [/autoit] [autoit][/autoit] [autoit]

    ; Werte ausgeben (Wert = Index bei Erstellung)
    With $o
    ConsoleWrite(.Alpha & @CRLF)
    ConsoleWrite(.Beta & @CRLF)
    ConsoleWrite(.Gamma & @CRLF)
    ConsoleWrite(.Delta & @CRLF & @CRLF)
    EndWith

    [/autoit] [autoit][/autoit] [autoit]

    ; Werte in Schleife ausgeben
    For $i = 1 To $aProps[0]
    ConsoleWrite(Execute('$o.' & $aProps[$i]) & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ; ??? Werte in Schleife zuweisen ???
    Global $aNewVal[4] = [10,20,30,40]
    For $i = 1 To $aProps[0]
    ; wie kann ich dynamisch den Property-Namen verwenden?
    ; so gehts nicht:
    Execute('$o.' & $aProps[$i]) = $aNewVal[$i-1] ; ==>> error: Statement cannot be just an expression.
    Next

    [/autoit] [autoit][/autoit] [autoit]

    _AutoItObject_Shutdown()

    [/autoit] [autoit][/autoit] [autoit]

    Func _Obj($_sProps)
    Local $self = _AutoItObject_Create()
    Local $aProps = StringSplit($_sProps, ';')
    For $i = 1 To $aProps[0]
    _AutoItObject_AddProperty($self, $aProps[$i], $ELSCOPE_PUBLIC, $i)
    Next
    ; Array mit Property-Namen speichern in eigener Property
    _AutoItObject_AddProperty($self, 'ArrayProps', $ELSCOPE_PUBLIC, $aProps)
    Return $self
    EndFunc

    [/autoit]
  • Spoiler anzeigen

    Geht auch mit Execute, mich wundert's eigentlich dass du nicht auf die Idee kommst das = $aNewVal[$i-1] in nen String zu packen... :D


    [autoit]

    #include "AutoitObject.au3"
    #include <Array.au3>

    [/autoit]

    [autoit][/autoit] [autoit]

    [s]
    [/s]

    [/autoit] [autoit]

    [s]_AutoItObject_StartUp()[/s]

    [/autoit] [autoit]

    [s]
    [/s]

    [/autoit] [autoit]

    [s]; Objekt mit Properties erstellen
    $o = _Obj('Alpha;Beta;Gamma;Delta')[/s]

    [/autoit] [autoit]

    [s]
    [/s]

    [/autoit] [autoit]

    [s]; Property-Namen anzeigen
    $aProps = $o.ArrayProps
    _ArrayDisplay($aProps)[/s]

    [/autoit] [autoit]

    [s]
    [/s]

    [/autoit] [autoit]

    [s]; Werte ausgeben (Wert = Index bei Erstellung)
    With $o
    ConsoleWrite(.Alpha & @CRLF)
    ConsoleWrite(.Beta & @CRLF)
    ConsoleWrite(.Gamma & @CRLF)
    ConsoleWrite(.Delta & @CRLF & @CRLF)
    EndWith[/s]

    [/autoit] [autoit]

    [s]
    [/s]

    [/autoit] [autoit]

    [s]; Werte in Schleife ausgeben
    For $i = 1 To $aProps[0]
    ConsoleWrite(Execute('$o.' & $aProps[$i]) & @CRLF)
    Next[/s]

    [/autoit] [autoit]

    [s]
    [/s]

    [/autoit] [autoit]

    [s]; ??? Werte in Schleife zuweisen ???
    Global $aNewVal[4] = [10,20,30,40]
    For $i = 1 To $aProps[0]
    ; wie kann ich dynamisch den Property-Namen verwenden?
    ; so gehts nicht:
    Execute('$o.' & $aProps[$i] & '= $aNewVal[$i-1]') ; ==>> error: Statement cannot be just an expression.
    Next[/s]

    [/autoit] [autoit]

    [s]
    [/s]

    [/autoit] [autoit]

    [s]_AutoItObject_Shutdown()[/s]

    [/autoit] [autoit]

    [s]
    [/s]

    [/autoit] [autoit]

    [s]Func _Obj($_sProps)
    Local $self = _AutoItObject_Create()
    Local $aProps = StringSplit($_sProps, ';')
    For $i = 1 To $aProps[0]
    _AutoItObject_AddProperty($self, $aProps[$i], $ELSCOPE_PUBLIC, $i)
    Next
    ; Array mit Property-Namen speichern in eigener Property
    _AutoItObject_AddProperty($self, 'ArrayProps', $ELSCOPE_PUBLIC, $aProps)
    Return $self
    EndFunc[/s]

    [/autoit]

    Sorry, da war ich wieder schneller als wie ich nachgedacht habe...
    Aber ich hatte das schonmal gemacht. Ich schau mal nach... :S

  • Achja, genau... Musste bisschen nachdenken... :D
    Mit _AutoItObject_AddProperty() kannst du existierende Werte auch überschreiben. Wenn du es "ganz sauber" haben willst lösche das Property vorher mit _AutoItObject_RemoveMember().

    Spoiler anzeigen
    [autoit]

    #include "AutoitObject.au3"
    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    _AutoItObject_StartUp()

    [/autoit] [autoit][/autoit] [autoit]

    ; Objekt mit Properties erstellen
    $o = _Obj('Alpha;Beta;Gamma;Delta')

    [/autoit] [autoit][/autoit] [autoit]

    ; Property-Namen anzeigen
    $aProps = $o.ArrayProps
    _ArrayDisplay($aProps)

    [/autoit] [autoit][/autoit] [autoit]

    ; Werte ausgeben (Wert = Index bei Erstellung)
    With $o
    ConsoleWrite(.Alpha & @CRLF)
    ConsoleWrite(.Beta & @CRLF)
    ConsoleWrite(.Gamma & @CRLF)
    ConsoleWrite(.Delta & @CRLF & @CRLF)
    EndWith

    [/autoit] [autoit][/autoit] [autoit]

    ; Werte in Schleife ausgeben
    For $i = 1 To $aProps[0]
    ConsoleWrite(Execute('$o.' & $aProps[$i]) & @CRLF)
    Next
    ConsoleWrite(@CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    ; ??? Werte in Schleife zuweisen ???
    Global $aNewVal[4] = [10,20,30,40]
    For $i = 1 To $aProps[0]
    _AutoItObject_AddProperty($o, $aProps[$i], $ELSCOPE_PUBLIC, $aNewVal[$i -1])
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ; Werte in Schleife ausgeben
    For $i = 1 To $aProps[0]
    ConsoleWrite(Execute('$o.' & $aProps[$i]) & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    _AutoItObject_Shutdown()

    [/autoit] [autoit][/autoit] [autoit]

    Func _Obj($_sProps)
    Local $self = _AutoItObject_Create()
    Local $aProps = StringSplit($_sProps, ';')
    For $i = 1 To $aProps[0]
    _AutoItObject_AddProperty($self, $aProps[$i], $ELSCOPE_PUBLIC, $i)
    Next
    ; Array mit Property-Namen speichern in eigener Property
    _AutoItObject_AddProperty($self, 'ArrayProps', $ELSCOPE_PUBLIC, $aProps)
    Return $self
    EndFunc

    [/autoit]
  • Hey, ich weiß dass das Thema schon erledigt ist, jedoch habe ich noch eine mögliche Möglichkeit gefunden. Bei dieser kann sogar das Objekt mit der For...In...Next durchlaufen werden. Ich denke es ist erwähnenswert da es ggf. noch anderen suchenden helfen könnte. Die Lösung stellt die Funktion _AutoItObject_AddEnum() dar.

    Dort werden 2 Funktionen angegeben die dafür sorgen dass nur ausgewählte Elemente (in diesem Fall Properties) durchlaufen werden. Die erste Funktion (der Parameter $sNextFunc) durchläuft alle Elemente. Der zweite Parameter ($sResetFunc) ist eigentlich gar nicht nötig, die dort angebende Funktion wird als erstes aufgerufen. Man kann da noch ein paar Sachen vorab verwaltet wenn man möchte. Z.B. wenn man ein System hat in verschiedenen For-Schleifen andere Properties auszugeben.

    Beide Funktionen müssen exakt 2 Parameter enthalten. Einmal der Verweis zu dem Objekt ($self) und einmal zu dem Iterator. Hier ist es wichtig das unbedingt den zweiten Parameter via ByRef übergeben wird da sonst der Iterator (z.B. beim zählen) nicht verändert werden kann.

    In der Hilfe steht zwar dass der letzte optionale Parameter nicht zu gebrauchen ist, aber das teste ich noch aus. Natürlich gibt es jetzt noch ein anschauliches Beispiel um die ausgewählten Properties dynamisch in einer For-Schleife abzurufen:

    Spoiler anzeigen
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <AutoItObject.au3>

    [/autoit] [autoit][/autoit] [autoit]

    _AutoItObject_Startup()

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    ; Array mit den Properties-Bezeichner.
    Global Const $asProperty[] = ['Alpha', 'Beta', 'Gamma', 'Delta']
    Global $iElement

    [/autoit] [autoit][/autoit] [autoit]

    ; Einfaches AutoIt Objekt
    Global $oObj = _AutoItObject_Create()
    _AutoItObject_AddProperty($oObj, 'Alpha', $ELSCOPE_PUBLIC, 1)
    _AutoItObject_AddProperty($oObj, 'Beta', $ELSCOPE_PUBLIC, 2)
    _AutoItObject_AddProperty($oObj, 'Gamma', $ELSCOPE_PUBLIC, 3)
    _AutoItObject_AddProperty($oObj, 'Delta', $ELSCOPE_PUBLIC, 4)
    ; Hier der Enum
    _AutoItObject_AddEnum($oObj, 'NextProperty', 'ResetProperty')

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    ; Alle Elemente durchlaufen.
    For $iElement In $oObj
    ConsoleWrite(' ' & $iElement & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    _AutoItObject_Shutdown()

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    ; Der zweite Parameter muss in jedem Fall ByRef übergeben werden.
    Func NextProperty($self, ByRef $iterator)

    [/autoit] [autoit][/autoit] [autoit]

    ; Sobald der Iterator alle Array Elemente durchlaufen hat soll der Schleifendurchlauf abgebrochen werden.
    ; Dafür muss ein Error Code zurückgegeben werden, ansonsten läuft es einfach weiter.
    If $iterator = UBound($asProperty) Then Return SetError(1)
    $iterator += 1 ; Das ist wohl klar...

    [/autoit] [autoit][/autoit] [autoit]

    Return Execute('$self.' & $asProperty[$iterator -1]) ; Inhalt des Elements zurück geben.
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; Da nicht gebraucht reicht es beides per ByVal zu übergeben.
    ; So meckert auch nicht die SciTE wenn man die Parameter nicht nutzt.
    Func ResetProperty($self, $iterator)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]


    Ob sich mit einem Workaround auch die Properties so in der For-Schleife ändern lassen kann ich noch nicht sagen. Arbeite daran, wäre wirklich praktisch wenn das so ginge. Vielleicht hat ja einer von euch eine Idee dazu? :D

  • Hab's geschaft! Mit einem Workaround lassen sich die ausgewählten Properties tatsächlich in einer For...In...Next Schleife auslesen und verändern. Habe dafür massiv den Code vergewaltigt, klappt aber wunderbar. Nennt mich einen Genie (so stolz war ich seit langem nicht mehr ^^)

    Spoiler anzeigen
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <AutoItObject.au3>

    [/autoit] [autoit][/autoit] [autoit]

    _AutoItObject_Startup()

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    Global $oObj = _Object()

    [/autoit] [autoit][/autoit] [autoit]

    For $o In $oObj
    ConsoleWrite($o() & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite(@CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    For $o In $oObj
    $o() = 5
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $o In $oObj
    ConsoleWrite($o() & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    Func _Object()
    Local $oObject = __Class().Object
    $oObject.Alpha = 1
    $oObject.Beta = 2
    $oObject.Gamma = 3
    $oObject.Delta = 4
    Return $oObject
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func __Class()
    Local $oClass = _AutoItObject_Class()
    $oClass.AddProperty('Alpha')
    $oClass.AddProperty('Beta')
    $oClass.AddProperty('Gamma')
    $oClass.AddProperty('Delta')
    $oClass.AddEnum('__Next__', '__Reset__')
    Return $oClass
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func __Next__(ByRef $self, ByRef $count)
    Local $asProperty[] = ['Alpha', 'Beta', 'Gamma', 'Delta']
    Local $i, $oTmp

    [/autoit] [autoit][/autoit] [autoit]

    If $count = UBound($asProperty) Then
    For $i = 0 To UBound($asProperty) -1
    $oTmp = Execute('$self.' & $asProperty[$i])
    _AutoItObject_AddProperty($self, $asProperty[$i], $ELSCOPE_PUBLIC, $oTmp())
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return SetError(1)
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    $count += 1

    [/autoit] [autoit][/autoit] [autoit]

    Return Execute('$self.' & $asProperty[$count -1])
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func __Reset__(ByRef $self, $count)
    Local $asProperty[] = ['Alpha', 'Beta', 'Gamma', 'Delta']
    Local $i

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To UBound($asProperty) -1
    _AutoItObject_AddProperty($self, $asProperty[$i], $ELSCOPE_PUBLIC, _Enum_Object(Execute('$self.' & $asProperty[$i])))
    Next
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    Func _Enum_Object($value)
    Local $oObject = __Class_Enum().Object
    _AutoItObject_AddProperty($oObject, '__value__', $ELSCOPE_PRIVATE, $value)
    Return $oObject
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func __Class_Enum()
    Local $oClass = _AutoItObject_Class()
    $oClass.AddMethod('__default__', '__Enum_Default__')
    Return $oClass
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func __Enum_Default__($self, $value = Default)
    $self.__value__ = ($value <> Default ? $value : $self.__value__)
    Return $self.__value__
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]