Dynamische Bedingungen erzeugen und speichern

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von GuentherA.

    Dynamische Bedingungen erzeugen und speichern

    Hallo Zusammen,

    ich muss für eine Anwendung verschiedene Zeiten mit loggen. Das bedeutet ich habe für jedes Log einen Timer, der in Abhängigkeit verschiedener Signalzustände läuft. Wird der Timer beendet, dann sollen verschiedene Daten dazu in ein Logfile geschrieben werden. Das ist soweit ja alles kein Problem. Wo ich allerdings hänge und mir den ein oder anderen Denkanstoss erhoffe ist, beim Zusammenstellen und Auswerten der notwendigen Abfrage. Ich möchte die Bedingung, ob ein Timer gestartet wird, nicht fest im Code verankern, sondern im Weiteren das über das GUI vom Benutzer zusammenstellen lassen. D.h. eine Bedienoberfläche, in der ich ein Signal aus einer Listbox auswähle, eine ComboBox mit "=,<>,<,>" und eine Textbox mit dem Wert, bei dem die Bedingung erfüllt ist. Und dann noch einen Button, mit dem ich weitere Bedingungen mit AND/OR daran hängen kann. Also im Sinne von "Wenn Signal1=1 UND Signal2=0 ist, dann..." oder "Wenn Signal1=0 ODER Signal2=0 AND Signal3=1.

    Hätte da jemand eine Idee für mich wie man das abbilden kann? Ich bin jetzt während meiner Suchen auf CodeDom gestoßen, da könnte ich dann - wenn ich das richtig verstanden hab - eine Function mit der Abfrage als string zusammen basteln und die auswerten. Wie "elegant" oder einfach die Lösung ist (wenn überhaupt möglich) weiß ich nicht... :)

    Danke um Voraus!
    LG Günther
    Hi
    bzgl. der Timer: Achte bei den Windows Forms-Timern darauf, dass die sehr unpräzise sind und je nachdem, ob bereits aufwändige Aufgaben ausgeführt werden oder noch ausstehen, gar nicht erst getriggert werden, bzw. ggf. erst sehr viel später. Es gibt für sowas bspw. System.Threading.Timers.Timer.

    CodeDom ist da gar nicht mal nötig für. Erstelle einfach ein Enum "ComparisonType", in das du die ganzen Vergleiche packst (Equal, NotEqual, Less, ...) und eine Klasse, in der du je zwei Signale ablegst. Außerdem gibt es noch eine Klasse, in der du And/Or wiederum ebenfalls über ein Enum bereitstellst.

    Die Architektur wäre natürlich noch stark verbesserungswürdig, du könntest auch eine Art Kompositum aufbauen.

    Viele Grüße
    ~blaze~
    Hi Blaze und danke für deine Antwort!

    Ja das mit den Forms Timern hab ich schon mal gelesen. Das werd ich noch umstellen.

    Den Rest habe ich aber noch nicht so ganz verstanden. Ich erstelle jetzt das Enum mit den Vergleichen. Weiters erstelle ich eine Klasse "Bedingung", die enthält ein Signal, das Enum und ein Feld für einen Wert. Dann halt noch einen Rückgabewert. Aber wie sollte der Aufbau mit der letzten Klasse funktionieren? Also das

    Außerdem gibt es noch eine Klasse, in der du And/Or wiederum ebenfalls über ein Enum bereitstellst.


    Und wie meinst du eine Art Kompositum? Also die Abfrage würde ich momentan als String zusammenbasteln... :) Meinst du das so in etwa?

    Danke und LG
    Günther
    Kompositum ist der Name eines gängigen Architekturpatterns. Es gibt dabei eine abstrakte Basis Komponente, ein Kompositum, das wiederum Komponenten kapselt und Blätter, die quasi Endpunkte darstellen.
    Im Folgenden ist Condition deine Komponente, ComparisonCondition ist ein Kompositum, da es eben wiederum die Condition-Instanzen Left und Right enthält und miteinander kombiniert.

    VB.NET-Quellcode

    1. Public MustInherit Class Condition
    2. Public MustOverride Function Evaluate() As Boolean
    3. End Class
    4. Public Class ComparisonCondition
    5. Inherits Condition
    6. Private _operator As ComparisonType
    7. Private _left, _right As Condition
    8. Public Sub New(left As Condition, right As Condition, [operator] As ComparisonType)
    9. If left Is Nothing Then Throw New ArgumentNullException(NameOf(left))
    10. If right Is Nothing Then Throw New ArgumentNullException(NameOf(right))
    11. _left = left
    12. _right = right
    13. _operator = [operator]
    14. End Sub
    15. Public ReadOnly Property Left As Condition
    16. Get
    17. Return _left
    18. End Get
    19. End Property
    20. Public ReadOnly Property Right As Condition
    21. Get
    22. Return _right
    23. End Get
    24. End Property
    25. Public ReadOnly Property [Operator] As ComparisonType
    26. Get
    27. Return _operator
    28. End Get
    29. End Property
    30. Public Override Function Evaluate() As Boolean
    31. Select Case [Operator]
    32. Case ComparisonType.And
    33. Return Left.Evaluate() AndAlso Right.Evaluate()
    34. Case ComparisonType.Or
    35. Return Left.Evaluate() OrElse Right.Evaluate()
    36. '...
    37. End Select
    38. End Function
    39. End Class

    Ich hoffe, der Code passt so, wie er ist. Mein VB ist inzwischen sehr eingerostet. Die eckigen Klammern werden gebraucht, da "Operator" ein Schlüsselwort von VB.Net ist, da muss das dann halt hin.
    Evaluate ist in Condition abstrakt definiert. Der Vorteil ist, dass es egal ist, wie das konkret implementiert ist. Diese Eigenschaft macht sich ComparisonCondition zunutze, indem es dich zwei wieder abstrakte Conditions vergleichen lässt.

    Der Vorteil dieser Struktur ist, dass du beliebig komplexe Ausdrücke darstellen kannst. Jedes left/right kann wieder eine Condition, wie bspw. eben ComparisonCondition, sein, usw. wodurch du eine Art "Bedingungsbaum" aufbauen kannst. Wenn du zusätzlich noch eine Klasse NotOperation (ha, wie toll dieser Name doch ist) einbaust, kannst du "komplexe Ausdrücke", wie "a Or Not b" mit einbauen.

    Dein Blatt wäre entsprechend die Klasse, die jeweils die beiden Signale vergleicht. Da weiß ich nicht genau, was alles drin sein soll, aber ggf. hilft dir ja genau dieses Pattern auch an dieser Stelle.

    Ich hoffe, es war halbwegs verständlich.

    Edit:
    Wikipedia-Link zum Thema Kompositum eingefügt

    Viele Grüße
    ~blaze~

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „~blaze~“ ()

    Hi blaze,

    wow! 1000 "dänker"! :)

    Da hab ich mal was zu tun und durch zu denken!

    Riesen dank mal soweit, auch für den Link...

    LG Günther

    Edit:
    OK, jetzt hast dus geschafft! - > ich hab einen Knopf im Hirn... :)

    Wie erzeuge ich jetzt eine Condition? Irgendwie beißt sich da die Katze in den Schwanz...

    Ich brauche doch jetzt noch eine Klasse, die ein Signal, einen Wert und einen Operanden enthält. Dies wäre ja dann eine Condition. Aber wenn ich diese neue Klasse von condition oder von ComparisonCondition ableite, dann passts ja auch nicht. Was übersehe ich da? :(

    Danke und LG
    Günther

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „GuentherA“ ()

    Ah warte, kann das stimmen?

    Eine Klasse, abgeleitet von Condition, erweitert um mein Signal, den Wert und den Operator.

    VB.NET-Quellcode

    1. Public Class SignalUeberwachung
    2. Inherits Condition
    3. Private m_ConditionSignal As ABB.Robotics.Controllers.IOSystemDomain.Signal
    4. Private m_Value As Single
    5. Private m_Operator As ComparisonType
    6. Public Property ConditionSignal As Signal
    7. Get
    8. Return m_ConditionSignal
    9. End Get
    10. Set(value As Signal)
    11. m_ConditionSignal = value
    12. End Set
    13. End Property
    14. Public Property Value As Single
    15. Get
    16. Return m_Value
    17. End Get
    18. Set(value As Single)
    19. m_Value = value
    20. End Set
    21. End Property
    22. Public Property [Operator] As ComparisonType
    23. Get
    24. Return m_Operator
    25. End Get
    26. Set(value As ComparisonType)
    27. m_Operator = value
    28. End Set
    29. End Property
    30. Public Sub New(Signal As ABB.Robotics.Controllers.IOSystemDomain.Signal, Value As Object, m_Operator As ComparisonType)
    31. MyBase.New()
    32. Me.m_Operator = m_Operator
    33. End Sub
    34. Public Overrides Function Evaluate() As Boolean
    35. Select Case [Operator]
    36. Case ComparisonType.Equals
    37. Return ConditionSignal.Value = m_Value
    38. Case ComparisonType.NotEquals
    39. Return ConditionSignal.Value <> m_Value
    40. Case ComparisonType.Less
    41. Return ConditionSignal.Value < m_Value
    42. Case ComparisonType.More
    43. Return ConditionSignal.Value > m_Value
    44. End Select
    45. End Function
    46. End Class


    dann wäre diese Klasse das Blatt in dem Aufbau oder?
    Ja genau. Achte darauf, dass du die Value-Eigenschaft noch setzt (der Value-Parameter sollte dann noch auf Single geändert werden). Selbiges gilt auch für ConditionSignal.
    Parameter werden übrigens in .Net kleingeschrieben und Felder sollten wohl mit _ beginnen, du kannst das m also theoretisch weglassen.
    Sofern du die Conditions unabhängig voneinander haben willst, würde ich außerdem dei Eigenschaften noch ReadOnly machen. Änderst du sonst eine der Eigenschaften beim einen Objekt, werden sie an allen Stellen ersetzt.

    Falls du das nicht nur schnell mal als Test implementiert hast: Dir fehlen noch Größer- und Kleiner-gleich. ;)

    Was noch ein Anstoß ist: Ggf. würdest du auch Single und Signal durch eine weitere Kompositums-Komponente ersetzen wollen, sodass du bspw. Signal mit Signal oder Signal mit Single oder Signal mit einer beliebigen Funktion vergleichen kannst.

    Viele Grüße
    ~blaze~
    @blaze: Das meiste deiner ComparisonCondition-Klasse gehört imo in die Basis-Klasse Condition.
    Sodass die ComparisonCondition all das fixnFertig erben kann, und nur noch das Evaluate() überschreiben muss.

    Allerdings sehe ich noch keine weiteren Condition-Erben.
    Also eine Basis-Klasse sollte schon von mehreren Klassen beerbt werden, sonst hats keinen Sinn.
    Da könnte man die Basis auch weglassen, und deren Logik gleich im "einzigen" "Erben" ansiedeln.




    Noch was anders:

    GuentherA schrieb:

    Bedienoberfläche...
    "Wenn Signal1=1 UND Signal2=0 ist, dann..." oder "Wenn Signal1=0 ODER Signal2=0 AND Signal3=1
    Dir ist hofflich klar, dass es äusserst schwierig wird, boolsche Algebra adäquat in einer komfortablen BedienOberfläche zu präsentieren.
    Weil da kriegst du Probleme mit Operator-Vorrängen, und Klammersetzung - Beispiel:

    Quellcode

    1. Signal1=0 OR Signal2=0 AND Signal3=1
    Bedeutet das

    Quellcode

    1. Signal1=0 OR (Signal2=0 AND Signal3=1)
    oder

    Quellcode

    1. (Signal1=0 OR Signal2=0) AND Signal3=1
    ?
    Und wie stellst du dir dazu die Oberfläche vor, die den User instand setzt, diese unterschiedlichen Klammerungen einzugeben?


    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Dann wären aber alle Conditions ComparisonConditions, d.h. auch die SignalUeberwachung. Das Leaf hatte ich ja nicht selbst ausprogrammiert, da ich nicht genau wusste, wie es aussehen sollte. ;)

    Bzgl. UI: Ich kann mir da zweierlei vorstellen: Ein TreeView, bei dem in die Tiefe die ANDs und auf einer Ebene die ORs stehen oder umgekehrt oder ein selbst programmiertes Steuerelement, das das schaltplanähnlich abbildet.

    Viele Grüße
    ~blaze~
    Man könnte das ganze auch textlich, über eine eigene kleine Scriptsprache, lösen.

    Ähnlich einer Mathematischen Formel:
    (Signal1=0 OR Signal2=0) AND Signal3=1

    Diese Formel muss man dann in einzelne Bestandteile auflösen und verarbeiten.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Hallo Zusammen,

    wollte mich nochmal abschlißend zu dem Thema melden. Ich habe die ganze Geschichte jetzt wie von @~blaze~ vorgeschlagen implementiert. Erweitert habe ich das ganze noch, dass die Conditions ausgewertet werden, wenn sich ein Signal ändert. Also an der Stelle nochmal vielen Dank für die Unterstützung!!!! :)

    Zum Thema GUI:
    Dazu hab ich ein paar Screenshots angehängt. Die gewählte Variante ist zwar ein bisserl ein hin und her schupfen der Bedingungen, ist aber für die Zwecke in Ordnung und es lassen sich auch die von dir @ErfinderDesRades erwähnten komplexen operationen abbilden.

    In jedem Fall funktionieren die Timer wie sie sollen :)

    Danke für Eure Unterstützung!

    LG Günther
    Bilder
    • 2017-02-09 15_32_12-LaRa Converter - by AMA-Tech GmbH (c) 2016.png

      51,39 kB, 1.025×769, 94 mal angesehen
    • 2017-02-09 16_00_12-Einstellungen.png

      42,38 kB, 1.025×769, 101 mal angesehen
    • 2017-02-09 16_00_31-Einstellungen.png

      43,03 kB, 1.025×769, 88 mal angesehen
    • 2017-02-09 16_00_43-Einstellungen.png

      43,97 kB, 1.025×769, 85 mal angesehen
    • 2017-02-09 16_00_49-Einstellungen.png

      43,78 kB, 1.025×769, 103 mal angesehen
    • 2017-02-09 16_00_56-Einstellungen.png

      44,79 kB, 1.025×769, 98 mal angesehen