WPF-Projekt [LRPC]

  • WPF

Es gibt 111 Antworten in diesem Thema. Der letzte Beitrag () ist von MichaHo.

    asusdk schrieb:

    es sei denn ich importiere wieder dataannotations, in dieser Klasse (gehen die Imports nicht irgendwie ProjektÜbergreifend ?)

    Ja, dann importiere diese. Klar, wenn du eine Auflistung von ValidationResult zurückbekommst muss der Compiler natürlich den Typ ValidationResult kennen.
    Wäre sehr schlecht wenn sowas Projektübergreifen ginge. Dann wäre etwas wie MVVM ja gar nicht machbar.

    Na sicher erhaltest du eine Auflistung. Es kann ja mehrere Fehler geben oder? Wäre ja doof wenn du nur den ersten Fehler zurückbekommst. Oder?

    Hier eine erklärung. Du musst lernen die Intellisense zu verwenden. Diese ist mehr als eine Hilfe. Sie verrät dir alles was du wissen musst.



    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hey @Nofear23m, da das ganze hier zum Lernen ist, hätte ich auch noch einen Vorschlag zur Validierung.
    Die Aufteilung in die 2 verschiedenen Klassen erscheint mir ehrlich gesagt ein wenig zu overengineered. Leichter könnte man es so machen:

    VB.NET-Quellcode

    1. Public Module ValidationUtils
    2. <Extension>
    3. Public Function Validate(entity As Object) As IList(Of ValidationResult)
    4. Dim validationResults As New List(Of ValidationResult)()
    5. If entity Is Nothing Then Return validationResults ' Maybe even throw ArgumentNullException. entity should probably never be Nothing.
    6. Dim validationContext As New ValidationContext(entity)
    7. Validator.TryValidateObject(entity, validationContext, validationResults, True)
    8. Return validationResults
    9. End Function
    10. <Extension>
    11. Public Function IsValid(entity As Object) As Boolean
    12. Return Validate(entity).Count = 0
    13. End Function
    14. End Module


    Einige Vorteile:
    • Weniger Code zu warten: Die ModelValidation<T> fliegt komplett raus (für diese eine Funktion braucht man auch keine Instanz. Shared/Static ist hier völlig ausreichend).
    • Validate() und IsValid() ist in ModelBase nicht mehr nötig, da sie als Extension verfügbar sind.
    • Man kann auf einmal jedes Objekt validieren, nicht nur ModelBase Instanzen. Generell vorzuziehen, da z.B. auch Models aus 3rd Party Libs vorhanden sein könnten, die nicht von ModelBase erben.
    • Etwas kleines: Validator.TryValidateObject schmeißt keine ValidationException. Die einzigen Exceptions, die auftreten könnten, wären laut doc die Argument(Null)Exception(s). Das lässt sich einfach durch den "Is Nothing" check umgehen. Try/Catch ist nicht nötig.
    Viele Grüße ^^
    @Nofear23m was ich jetzt gerade nicht verstehe,

    wieso funktioniert es bei dir, ohne expliziten erneuten Import der DataAnnotations ? Wie in Post 40 von @flori2212 angemerkt musste ich diese explizit nochmals importieren. bei deinem Video scheint es so als hättest du dies nicht machen müssen, was hat es damit aufsich ?

    Die Aufteilung in die 2 verschiedenen Klassen erscheint mir ehrlich gesagt ein wenig zu overengineered. Leichter könnte man es so machen:

    Fände ich ansich auch besser, da es durchaus "verwirrender" ist wenn es sich schon wieder auf mehr klassen aufteilt als von nöten, aber ich halte mich hier an das was NoFear vorgibt, da ich wohl beie Varianten erstmal verstehen lernen muss. Prinzipiel bin ich aber ein Freund von So wenig Klassen/Instanzen wie nur irgendmöglich. Wohl auch geschmackssache. ^^

    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Hallo @shad

    Auch eine Möglichkeit. Klar, einige Dinge sind einleuchtend.
    In diesem Fall (in einem Model) möchte ich allerdings im Grunde nur meine Dinge testen. Da fällt der Rest sowieso weg weshalb ich auf eine Extension gerne verzichten möchte.
    Auch ein Grund hierfür ist eben das ich es dann auf jedes Objekt anwenden könnte. Das fällt uns dann im ViewModel auf den Kopf, dazu kommen wir aber noch. Denn auch dirt gibt es Methoden welche allerdings anders funktionieren, dort könnte dann jemand auf die Idee kommen die Extension zu verwenden um zu Validieren. Es kommt True zurück obwohl dem nciht so ist. Schlecht. Das ist der Hauptgrund warum ich es so mache.

    shad schrieb:

    Validator.TryValidateObject schmeißt keine ValidationException. Die einzigen Exceptions, die auftreten könnten, wären laut doc die Argument(Null)Exception(s).

    Das stimmt so nicht. Es ist richtig - laut Docu. Aber da speielen noch andere Faktoren mit. Siehe z.b. hier eine von mir gerade erzwungene InvalidCastException =O

    Grüße
    Sascha

    Edit: @asusdk weil ich vorher schon einen Verweis hinzugefügt hatte.
    Bilder
    • Exception.png

      19,68 kB, 696×121, 62 mal angesehen
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Alles klar, dann macht es in diesem Fall Sinn. Dennoch würde ich die ModelValidation<T> entfernen und die Validate() Methoden nicht als Extensions, sondern direkt in die ModelBase Klassen packen. Wenn diese Methoden sowieso nur auf ModelBases angewendet werden sollen, gibt es doch keinen Grund, sie aus dieser Klasse zu entfernen, oder übersehe ich hier etwas?
    Als Alternative könnte man bei den Extensions auch einfach das "Object" zu "ModelBase" ändern. Problem gelöst.

    Die Exception ist tatsächlich unterwartet - wie hast du die denn genau erzwungen? Man lernt nie aus..

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

    shad schrieb:

    und die Validate() Methoden nicht als Extensions

    Ich habe keine Extensions drinnen. Nur eine Statische Methode, die soweit auch statisch bleiben kann. Ich habe es deshalb in ein eigenes File gepackt weil ich es nicht mag wenn ich Statische Methoden mit nicht stiaschen mische. Da bin ich eigen. Aber du bist gerne eingeladen einen PullRequest zu erstellen oder hier den Code zu Posten, dann gehen wir das durch. Wenn möglich getesteten.

    shad schrieb:

    Die Exception ist tatsächlich unterwartet - wie hast du die denn genau erzwungen?

    z.b. so

    VB.NET-Quellcode

    1. <MaxLength(15)>
    2. Public Overridable Property Current As Integer


    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Nofear23m schrieb:

    Ich habe keine Extensions drinnen.

    Ja, das war auf meinen Code von vorhin bezogen.

    Nofear23m schrieb:

    weil ich es nicht mag wenn ich Statische Methoden mit nicht stiaschen mische. Da bin ich eigen.

    Daran ist absolut nichts auszusetzen. Im Gegenteil, in den meisten Fällen macht das mmn auch Sinn zwecks Übersichtlichkeit. :)


    Was ich gerade erreichen möchte ist, dass dieser Code hier entweder in eine statische Methode umgewandelt wird, oder in die ModelBase wandert:

    VB.NET-Quellcode

    1. Public Class ModelValidation(Of T As ModelBase)
    2. Public Function Validate(entity As T) As IEnumerable(Of ValidationResult)
    3. Dim validationResults As List(Of ValidationResult) = New List(Of ValidationResult)()
    4. Dim validationContext As ValidationContext = New ValidationContext(entity, Nothing, Nothing)
    5. Try
    6. Validator.TryValidateObject(entity, validationContext, validationResults, True)
    7. Catch ex As Exception
    8. Debug.WriteLine(String.Format("FEHLER Validate: {0}", ex.ToString))
    9. End Try
    10. Return validationResults
    11. End Function
    12. End Class


    Warum?
    Weil es keinen Grund gibt, für diese Validierung eine neue Klasse und für jede einzelne Validierung eine neue Instanz zu erstellen.
    Im Gegenteil - die Validierung kann komplett funktional implementiert werden.

    Als Beispiel hier die abgeänderte Version von meinem Post oben, hier allerdings nicht mehr für alle Objekte, sondern nur noch für ModelBase Instanzen.
    Anmerkung: Hier ist es als extension implementiert, aber man kann genau die gleiche Logik auch ganz einfach als static umschreiben. Was euch auch immer besser gefällt. ;)

    VB.NET-Quellcode

    1. Public Module ModuleValidator
    2. <Extension>
    3. Public Function Validate(entity As ModelBase) As IList(Of ValidationResult)
    4. Dim validationResults As New List(Of ValidationResult)()
    5. If entity Is Nothing Then Return validationResults
    6. Dim validationContext As New ValidationContext(entity)
    7. Validator.TryValidateObject(entity, validationContext, validationResults, True)
    8. Return validationResults
    9. End Function
    10. <Extension>
    11. Public Function IsValid(entity As ModelBase) As Boolean
    12. Return Validate(entity).Count = 0
    13. End Function
    14. End Module


    Hier entwickelt sich jetzt allerdings eine Anschlussfrage: Wenn die Validierung wirklich nur für ModelBases so benutzt werden soll (so habe ich es zumindest verstanden), dann spricht nichts dagegen, die ganze Logik direkt in diese Klasse zu packen.

    VB.NET-Quellcode

    1. Public MustInherit Class ModelBase
    2. ' <Property Snip>
    3. Public Function Validate() As IList(Of ValidationResult)
    4. Dim validationResults As New List(Of ValidationResult)()
    5. Dim validationContext As New ValidationContext(Me)
    6. Validator.TryValidateObject(Me, validationContext, validationResults, True)
    7. Return validationResults
    8. End Function
    9. Public Function IsValid() As Boolean
    10. Return Validate().Count = 0
    11. End Function
    12. End Class


    In beiden Fällen kann man Code entfernen, was mein eigentliches Ziel ist. Desweiteren finde ich es so leichter zu verstehen.

    Der Grund, warum ich mich deswegen hier einmische ist übrigens, weil ich mich erinnere, dass @asusdk irgendwann einmal geschrieben hat, dass ihn bei WPF/MVVM die vielen Klassen ein wenig abschrecken. Deswegen mein Vorschlag, um die gesamte Codelänge möglichst klein und verständlich zu halten.
    Nichtsdestotrotz - das ganze ist nur ein Vorschlag. Schaut es euch gerne an, aber nehmt dann bitte die Versionen, die für euch am verständlichsten sind!


    Und noch abschließend zum try/catch: Der Fall ist gemein. Und Achtung, jetzt wird es subjektiv:
    Ich finde nicht, dass man das try/catch hier einführen soll. Die InvalidCastException die in deinem Beispiel auftritt, ist ein Programmierfehler, also ein Bug in unserem Code. MaxLength sollte nur auf Arrays/Strings angewendet werden. Auf Ints kommt es dann natürlich zu Fehlern. Allerdings ist dieser Fehler speziell einer, den dann der Programmierer erzeugt hat, nicht der User.
    Sprich, die Exception ist hier angebracht, damit wir auch schnell merken, wenn wir falschen Code geschrieben haben.
    Für Benutzereingaben (und hier ist der Punkt, an dem Exception-Handling sinnvoll wird!) sollte TryValidate niemals Exceptions werfen. Oder kennst du noch ein anderes Beispiel, bei dem man den Flow nicht durch falsche Attribute brechen kann?

    Allgemein hat hier MS einen Fehler gemacht. Anstatt einer InvalidCastException sollte eine andere geworfen werden. Meinetwegen eine InvalidOperationException, die in der Message sagt, dass das Attribut an die falsche Property gesetzt wurde. Aber da kann man leider nichts machen.
    Hallo

    Ja, die Methode können wir so übernhemen. Ich werde es dann Commiten.
    Du hast schon recht. Für AsusDk ist es sicher einfacher wenn die Methoden einfach so in der ModelBase vorhanden sind.

    Für mich ist es besser wenn ich alle geordnet in seperaten Klassen habe und in der jeweiligen Basisklasse dann Instanzen erzeuge, ich finde es so geordneter, aber ich bin auch jemand der sich nicht an vielen Klassen stört.

    Was das Try/Catch betrifft gebe ich dir vollkommen recht.
    Ich habe dies aus einem Relikt drinnen und aus einer App übernommen in welcher der User über die Settings z.b. selbst solche Werte einstellen kann welche dann auch auf das Datenbankmodell übernommen werden und da hatt ich dann so zum probieren drinnen, hätte ich aber dran denken sollen das rauszunehmen. Fliegt also. Super Input.

    Grüße
    Sascha

    Edit: Commit erstellt
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Schaut es euch gerne an, aber nehmt dann bitte die Versionen, die für euch am verständlichsten sind!

    naja ich muss mich da raushalten, da ich bislang (obwohl ich es seit 2 stunden Versuche) keine der Varianten verstehe.

    Ich habe nun verstanden wie ich mit den von NoFear implementierten Klassen an die Fehlermeldungen komme, aber was die Funktionen letztenendes wirklich tun, leider absolut (noch) kein plan.

    VB.NET-Quellcode

    1. Public Shared Function ValidateEntity(Of T As ModelBase)(entity As T) As IEnumerable(Of ValidationResult)
    2. Return New ModelValidation(Of T)().Validate(entity)
    3. End Function

    Ich habe es zwar durchaus versucht, allerdings verstehe ich bislang nicht, wie genau der Code funktioniert, bislang ist mir nur bekannt das er in der ModelBase integriert ist, und sich dann noch über 2 Weitere Klassen erstreckt, mal gucken ob ich heute abend wenn ich Ruhe habe (Auf arbeit ist leider nichts mit konzentrieren) dahintersteigen kann was er da eigentlich tut, bislang wirkt er eher sehr verwirrend auf mich. Naja dranbleiben versuchen und zur Not nochmal fragen =)

    Nachtrag:
    @Nofear23m
    Für mich ist es besser wenn ich alle geordnet in seperaten Klassen habe und in der jeweiligen Basisklasse dann Instanzen erzeuge, ich finde es so geordneter, aber ich bin auch jemand der sich nicht an vielen Klassen stört.


    Nur aus persönlichem interesse, stört es dich denn nicht wenn du dann zum nachvollziehen einer Funktion 3 mal in andere Dateien reinmusst, und dann wieder in die andere weil dann musst du ja da nachlessen, derweil hab ich schon wieder vergessen was in der Anderen Klasse stand, ist es einfach nur 1 File, kann cih hoch und runter scrollen. Oft Kopiere ich mir sogar den Inhalt einer Klasse ins NotePad(Editor) und halbiere die Größe von VS, einfach damit ich 2 Methoden oder dergleichen direkt nebeneinander habe.

    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    asusdk schrieb:

    und sich dann noch über 2 Weitere Klassen erstreckt

    Ist nicht mehr der Fall. Siehe meinen letztn Post. Ich habe auch bereits Commited.

    asusdk schrieb:

    stört es dich denn nicht wenn du dann zum nachvollziehen einer Funktion 3 mal in andere Dateien reinmusst

    Ne, keinesfalls. Im Gegenteil. Wenn eine Benamsung stimmt dann muss ich in diese Methode ja nicht rein. Wozu auch. Ich weis ja was Validate macht. Validieren - welche überraschung.

    Solle ich mal wissen wollen was da abgeht lass ich die IDE für mich arbeiten und drücke ich F12. Schups bin ich in der Methode.
    Oh, sie nutzt einen ModelValidator um ein Model-Objekt zu Validieren. OK, mehr will ich nicht wissen. Falls doch dann den Cursor hin und F12 und weiter gehts.

    Ich will nicht in einer Methode zu langen Code haben. Nachdem ich eine Funktionalität Implementiert habe interessiert mich nicht mehr WIE ich das implementiert habe. Es funktioniert, denn das habe ich im Idealfall schon mal getestet. Wenn ich jetzt wissen will was sich hinter einer Funktion verbirgt will ich nicht 50 Zeilen Code vorfinden (in diesem Fall sind es keine 50 Zeilen, aber ich spreche jetzt Allgemein) um diese dann zu Analysieren. Der Name einer Methode muss mir alle sagen können. Ist sicher auch geschmacksache aber gut.

    Der wohl größte Unterschied ist das ich meine Art uns weise so wiederverwenden kann. z.b. in einem NuGet-Paket oder einer dll.
    Dann natürlich mit Public Class ModelValidation(Of T As Object)

    Man merkt du arbeitest nicht aktiv mit der IDE. VisualStudio ist ein Traum Werkzeug.
    Ich kann sogar 3 Methoden gleichzeitig ansehen, oder soviele ich will.



    Und sogar von ein und der selben Klasse kann ich mir zwei methoden gleichzeitig ansehen. Its Magic!!!



    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ok, F12, WoW, das kannte ich nicht, das ist schon mal echt klasse.

    Wie hast du die 3 Klassen untereinander gemacht, oder die 2 ?

    Der wohl größte Unterschied ist das ich meine Art uns weise so wiederverwenden kann. z.b. in einem NuGet-Paket oder einer dll.

    Ja das macht für dich durchaus Sinn, aber so ein Fall wird bei mir nie eintreten. Ich arbeite sehr ungern über .dlls lieber mach ich mir das UserControl oder um was es auch geht wieder selbst als Code rein, in eine dll kann ich nicht rein und gucken, um zu sehen was diese macht oder um diese anzupassen, dazu dann Imports, Verweise usw. - Ist aber vermutlich auch wieder Geschmackssache
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    asusdk schrieb:

    Ich arbeite sehr ungern über .dlls

    Deshalb gibt es NuGet Pakete.

    Un klar kannst du da reinsehen. Wenn es dein eigenes NuGet Paket ist hast du das Projekt ja. Im Idelfall ja auch in einer Quellcodeverwaltung. Sprich du kannst sogar Online reingucken - also z.b. auch in der Firma wo du kein VS hast. ;)

    Teilen eines Dokuments geht indem du rechts das Symbol nach unten schiebst.



    Du Merkst schon, der richtige Umgang mit der IDE ist wichtig. So kann man extrem viel Zeit und ärger sparen. Die Entwickler denken sich schon was dabei.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Du Merkst schon, der richtige Umgang mit der IDE ist wichtig. So kann man extrem viel Zeit und ärger sparen. Die Entwickler denken sich schon was dabei.


    Ja, durchaus , nur muss man auch erstmal davon erfahren, sowas erklärt sich ja nicht von selbst, und man aknn nur benutzen was man auch kennt / von dem man weis


    Nachtrag:
    Teilen eines Dokuments geht indem du rechts das Symbol nach unten schiebst.


    dann zeigt er mir leider nur 2 x das selbe File an ? Siehe Anhang
    Bilder
    • d.JPG

      245,4 kB, 2.443×1.192, 51 mal angesehen
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Hallo,

    wieder ein kurzer Einwurf.
    In letzter Zeit enddecke ich (mehr oder weniger) durch Zufall soche Praktischen Funktionen von VS. Beispiel F12 oder jetzt das teilen der Code Ansicht.

    Gibt es da im Internet vielleicht eine Art Zusammenfassung wo diese ganzen Funktionen stehen.
    Weil ich bin da noch nicht so ganz vertraut mit den ganzen Funktionen.

    Zum Projekt: So weit dürften die Models jetzt ja fertig sein. Ich wollte nochmals zum Verständnis für mich nachfragen. Diese DataAnnonations mit dem Validate, kann man diese dann im View (per Binding) ganz einfach anzeigen lassen, oder für was machen wir das?

    Viele Grüße
    Florian
    ----

    WebApps mit C#: Blazor

    asusdk schrieb:

    dann zeigt er mir leider nur 2 x das selbe File an ?

    Sorry, habe ich dich falsch verstanden. Du kannst ALLE Fenster Docken oder Floaten (frei schweben lassen). Einfach das Fenster nehmen und Abdocken und wo anders andocken. Einfach mal probieren. Zieh das Fenster herum und schieb es mal bis so DockingSymbole kommen, dort kannst du dann bestimmen wo und wie es nun gedockt werden soll.

    flori2212 schrieb:

    In letzter Zeit enddecke ich (mehr oder weniger) durch Zufall soche Praktischen Funktionen von VS. Beispiel F12

    Wenn du einen Rechtsklick auf einen Funktionsnamen machst siehst du im ContextMenu "Gehe zu Definition". Wie der Name sagt geht er da zur Definition der Methode. Und daneben steht der ShortKey - nämlich F12. Kein Hexenwerk also. Man muss nur ein wenig rumprobieren. Dann kommt das alles von selbst.

    flori2212 schrieb:

    Gibt es da im Internet vielleicht eine Art Zusammenfassung wo diese ganzen Funktionen stehen.

    Gibt es sicher, vieleicht findest auch was auf YouTube. Am besten einfach meine Videos aufmerksam(!!) ansehen dann sieht man das ein oder andere.
    Beispiel: Das mit F12 habe ich sogar explizit in einem Video angesprochen!! Sieht mans mal wieder ;)

    flori2212 schrieb:

    Diese DataAnnonations mit dem Validate, kann man diese dann im View (per Binding) ganz einfach anzeigen lassen, oder für was machen wir das?

    Korrekt. Wir binden das Resultat dann in unser ViewModel ein und durch Bindig werden die ValidationErrors auch Visuell dargestellt und der "Speichern" Button wird nicht aktiv solange es Fehler gibt.
    Aber wir haben in den Models damit schonmal den Grundstein gelegt um später im ViewModel nicht mehr so viel Arbeit zu haben. Ausserdem soll das Model ja vorgeben was es "kann und darf". Das ViewModel hört nur darauf.

    Aber was anderes:

    @asusdk jetzt musste mal wegsehen, ich will dich nicht überfordern. Aber für flori oder die anderen ist es vieleicht was.
    Ich habe ein UnitTest-Projekt angelegt. da wir das Model in einem eigenen Projekt haben, und dieses getrennt von den anderen ist können wir nun super einfach unsere DataAnnotations für jedes einzelne Property prüfen, auf alle möglichen Werte, ohne viel Aufwand und Tipparbeit. In wenigen Millisekunden wissen wir bescheid. Ich habe jetzt nicht jede möglichkeit durchgetestet, aber doch zumindest alle Properties auf Annotationen geprüft. Also ob alle Properties eine Annotation aufweisen.

    Wie man sehen kann kann ich die Tests mit einem Klick alle Ausführen und weis sofort das alles so ist wie ich das haben möchte.


    Ändere ich nun eine Annotation z.b. lasse ich beim Produktpreis auf 0 zu schlägt mindestens ein Test fehl da ich das nicht wollte. Zumindest sagt mein Test "Nein"



    Ich Push das dann gleich hoch.

    Hier die Tests:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports LRPC.Model
    2. <TestClass>
    3. Public Class AnnotationTests
    4. <TestMethod> <TestCategory("AnnotationTests.Product")> Public Sub CreateProductInstanceMustBeInvalid()
    5. Dim sut As New Product()
    6. Assert.IsFalse(sut.IsValid)
    7. End Sub
    8. <DataRow("TestProduct", 1, 1, 1, 1, 1, 1, "", 0)>
    9. <DataRow("TestProduct", 0, 1, 1, 1, 1, 1, "", 1)> 'Zu kleiner Preis
    10. <DataRow("TestProduct", -30.2, 1, 1, 1, 1, 1, "", 1)> 'Zu kleiner Preis
    11. <DataRow("TestProduct", 1, -1232.3, 1, 1, 1, 1, "", 1)> 'Zu kleiner KitPreis
    12. <DataRow("TestProduct", 1, 6526548795, 1, 1, 1, 1, "", 1)> 'Zu hoher KitPreis
    13. <DataRow("TestProduct", 1, 6526548795, 10000, 1, 1, 1, "", 2)> 'Zu hoher KitPreis und Instandhaltungsmiete
    14. <DataRow("TestProduct", 1, 6526548795, 10000, 1, 1, 1, "", 2)> 'Zu hoher KitPreis und Instandhaltungsmiete
    15. <DataRow("TestProduct", 1, 1, 1, -41, -2847, 1, "", 2)> 'Negativwert für Stunden und Verbrauchsmaterial
    16. <DataRow("TestProduct", 1, 1, 1, 1, 1, 23654, "", 1)> 'Zu hohe Versandkosten
    17. <DataRow("", -1, -1, -1, -1, -1, -1, "", 7)> 'Alles falsch
    18. <TestMethod> <TestCategory("AnnotationTests.Product")> Public Sub ProductWithWrongDataMustHaveTheCorrectValidationErrorsCount(
    19. name As String, price As Object, kitPrice As Object,
    20. rentMaintenance As Object, hours As Object,
    21. consumablePrice As Object, shippingFee As Object, comment As String, validationErrorCount As Integer)
    22. Dim sut As New Product() With {.ConsumablesPrice = CDec(consumablePrice), .HoursOfCheck = CDbl(hours), .MaintenanceKitPrice = CDec(kitPrice), .ProductName = name,
    23. .ProductComment = comment, .ProductPrice = CDec(price), .ShippingFee = CDec(shippingFee), .RentsUntilMaintenance = CDbl(rentMaintenance)}
    24. Assert.AreEqual(validationErrorCount, sut.Validate.Count())
    25. End Sub
    26. <TestMethod> <TestCategory("AnnotationTests.Product")> Public Sub CreateProductInstanceMustCreateAGuid()
    27. Dim sut As New Product()
    28. Assert.AreNotEqual(Guid.Empty, sut.Id)
    29. End Sub
    30. <TestMethod> <TestCategory("AnnotationTests.Settings")> Public Sub CreateSettingInstanceMustBeValid()
    31. Dim sut As New Settings()
    32. Assert.IsTrue(sut.IsValid)
    33. End Sub
    34. <DataRow(1, 1, "C:\", 0)>
    35. <DataRow(0, 0, "C:\", 2)>
    36. <TestMethod> <TestCategory("AnnotationTests.Settings")> Public Sub SettingWithWrongDataMustHaveTheCorrectValidationErrorsCount(
    37. labor As Object, priceSplitter As Object, xmlPath As String, validationErrorCount As Integer)
    38. Dim sut As New Settings() With {.Labor = CDec(labor), .PriceSplitter = CDec(priceSplitter), .XmlPath = xmlPath}
    39. Assert.AreEqual(validationErrorCount, sut.Validate.Count())
    40. End Sub
    41. End Class


    Grüße
    Sascha

    Edit: Push Online
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

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

    Hallo,

    eine sehr interessante Sache mit den Unit Tests.
    Blöderweise verstehe ich es gerade überhaupt nich, "was" du mit diesem Test überhaupt testest.
    Wenn du mir da kurz auf die Sprünge helfen könntest.

    Viele Grüße
    Florian
    ----

    WebApps mit C#: Blazor
    Aber nur kurz, alles weitere würde ich in einem anderen Thread machen.

    Vorweg: Sowas würde ich nicht testen, ich Teste ja im Grunde nur .Net Code. Im besten Fall kontrolliere ich mich hier ob ich eh brav auf jedem PRoperty eine Annotation gepackt habe. Mehr nicht.
    Es soll als Beispiel dienen.

    Aber, sehen wir uns mal folgendes an:

    VB.NET-Quellcode

    1. <TestMethod> <TestCategory("AnnotationTests.Settings")> Public Sub SettingWithoutXmlPathMustHaveTheRightValidationError()
    2. Dim sut As New Settings() With {.XmlPath = ""}
    3. Assert.IsFalse(sut.IsValid, "Das Model sollte Invalid sein, war aber Valid!")
    4. Assert.AreEqual(1, sut.Validate.Count, "Es sollte nur einen Validationerror geben dürfen, es gab aber keinen oder mehr!")
    5. Console.WriteLine($"Error on '{sut.Validate.First.MemberNames.First}' with ErrorMessage '{sut.Validate.First.ErrorMessage}'")
    6. Assert.AreEqual(NameOf(sut.XmlPath), sut.Validate.Single.MemberNames.First)
    7. End Sub


    Die Methode sagt: Setting ohne XMLPath muss den richtigen Validiersfehler aufweisen.
    Also prüfen wir genau das. Wir erstellen ein Objekt vom Typ Settings. Diesem Objekt weisen wir einen unserer Meinung nach ungültigen Pfad zu. Nämlich "".
    OK, Als erstes Prüfen wir ob das Model nun eh nicht Valid ist. Wäre es Valid würde der Test nun bereits in einen Fehler laufen mit der Nachricht welche ich angegeben habe.
    Gut, als nächstes prüfen wir ob es genau einen Fehler bei der Validierung gibt. Denn die anderen Properties sollten korrekt sein. Ist dies nicht der Fall.... eh schon wissen.

    Zu guter letzt prüfen wir nun noch ob der richtige ValidationError auftaucht, es könnte ja sein das ein anderen Property einen Error zurückgibt und wir denken das eh alles gut ist weil ...... ein Error wars ja, nur der Falsche vieleicht. Also prüfen wir ob der Member des ValidationErrors auch wirklich das Property "XmlPath" ist. Allerdings natürlich Dynamisch mit NameOf, so müssen wir den Test nicht abändern, sollten wir mal das Property unbenennen.

    Aber in weiterer Folge werde ich noch mehr Tests implementieren, da wird es dann vieleicht klarer.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Nofear23m schrieb:

    Aber nur kurz, alles weitere würde ich in einem anderen Thread machen.

    Vielen, vielen Dank, das hat schon gereicht fürs erste :thumbsup:

    ----

    So, wie geht es jetzt hier weiter.
    Ich würde vorschlagen, da (wie ich annehme) alle Modelklassen fertig sind, @asusdk jetzt als erstes ein View (wie er sich es vorstellt) gestaltet und wir helfen ihm dann das passende ViewModel zu erstellen.

    Viele Grüße
    Florian
    ----

    WebApps mit C#: Blazor

    flori2212 schrieb:

    Wenn du mir da kurz auf die Sprünge helfen könntest


    flori2212 schrieb:

    jetzt als erstes ein View (wie er sich es vorstellt)

    Würde ich auch sagen. @asusdk her mit ner Skizze. Kann auch ruig eine gute Benutzerführung haben. Weil das mit den zwei Listboxen finde ich jetzt nicht so Prikelnd.

    Ich mach derweil auch einen kleinen Antwurf, vieleicht @flori2212 und/oder @MichaHo ja auch und dann schaun wir mal welches was wir von welchem Entwurf für das HauptView verwenden. :thumbup:

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##