Property Value as string setzen

  • VB.NET
  • .NET (FX) 4.0

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

    Property Value as string setzen

    Moin Leute,

    kleines aber nerviges Problem.
    Ich speichere Eigenschaften meiner Klassen in einer Config.cfg.

    Sieht ca so aus

    VB.NET-Quellcode

    1. Dim t = config.GetType
    2. Dim fieldName As String
    3. Dim propertyValue As Object = Nothing
    4. Dim propertyType As Type
    5. Dim arrLines As New List(Of String)
    6. For Each pi As PropertyInfo In t.GetProperties(BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic)
    7. fieldName = pi.Name
    8. propertyType = pi.PropertyType
    9. propertyValue = pi.GetValue(config)
    10. Dim lin As String = fieldName.ToString & Chr(9) & propertyValue.ToString & Chr(9) & propertyType.ToString
    11. arrLines.Add(lin)
    12. Next
    13. If File.Exists(fmMain.f_Config) Then
    14. File.Delete(fmMain.f_Config)
    15. End If
    16. Dim fi = File.Create(fmMain.f_Config)
    17. fi.Close()
    18. fi.Dispose()
    19. Dim sw As StreamWriter = New StreamWriter(fmMain.f_Config)
    20. For Each l In arrLines
    21. sw.WriteLine(l)
    22. Next
    23. sw.Close()
    24. sw.Dispose()




    Jetzt will ich das ganze einlesen. Solange die Eigenschaft ein String ist, kein ding.
    Jetzt steht aber z.B. ein Boolean und ein Integer Wert dabei, manchmal auch ein Checkstate.
    In der Config Datei siehts so aus:

    username System.String userpw test System.String mainlink 1 System.String sublink_1 1 System.String sublink_2 4 System.String sublink_3 6 System.String blnAuto True System.Boolean monday False System.Boolean tuesday False System.Boolean wednesday False System.Boolean thursday False System.Boolean friday False System.Boolean saturday False System.Boolean sunday False System.Boolean repeat 0 System.Int32

    Wenn ich da jetzt eine Zeile einese, z.B. diese sunday False System.Boolean, wie zur Hölle kriege ich es hin, die Eigenschaft beim Einlesen wieder zu setzen:

    VB.NET-Quellcode

    1. For Each l_cfg In arrLines
    2. For Each pi As PropertyInfo In t.GetProperties(BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic)
    3. fieldName = pi.Name
    4. propertyType = pi.PropertyType
    5. If l_cfg.Split(Chr(9))(0) = fieldName Then
    6. pi.SetValue(config, l_cfg.Split(Chr(9))(1), Nothing)
    7. Exit For
    8. End If
    9. Next

    Wie konvertiere ich das value aus der Datei, wenn ich vorher nicht weiß, in was ich konvertieren muss?
    Dim Value = convert.to(System.Boolean.gettype, value aus textdatei)

    Hilft mir mal jemand ? :D

    BTW Falls jemand das überschreiben der Config Datei verbessern kann, gerne auch dabei.
    ~Wir leben zwar alle unter dem gleichen Himmel, aber es haben nicht alle den gleichen Horizont~
    @razzzer530i Probierma und frag den Typ des Objects ab:

    VB.NET-Quellcode

    1. If TypeOf(obj) Is String Then
    2. MessageBox("String")
    3. End If
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Funzt nich.
    Das objekt ist ja immer ein string, da ich aus einer textdatei auslese.
    ich müsste quasi gucken, ob der variablenname von System.Boolean in der line enthalten ist. Das macht das ganze aber wieder total starr.

    Also helfen würde auch sowas:

    For each strk[struktur] in System if strk.name = System.String then ConvertTo[strk,value] nexr

    Verständlich was ich meine?
    Das ganze muss easy und flexibel sein. Tue mich da gerade echt schwer, wobei es doch sicher so einfach ist.
    ~Wir leben zwar alle unter dem gleichen Himmel, aber es haben nicht alle den gleichen Horizont~
    @razzzer530i Dann probierma, mit DEIN_TYP.TryParse(...) zum richtigen Ergebnis zu kommen.
    Hier musst Du die Reihenfolge beachten, also der String wäre in der Reihenfolge ganz hinten.
    Zuerst DateTime, dann Boolean, dann Double und Integer.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi.

    "Auf jeden Fall prüfen."

    Hier kann mit einem Siebverfahren gearbeitet werden.
    Alles ist von "String" aus auszuwerten.
    Ich durchlaufe die Werte mittels einer Schleife, vergleiche dann nach dem Objekttyp vom einfachsten zum komplexesten.
    True/false -> Boolean - sehr einfach...

    Pseudocode:

    Quellcode

    1. For each WASDENN in DIEDINGE
    2. If WASSDENN.ToLower.Contains("true") -> hier nun raus aus der schleife und True zurückgeben...
    3. If WASSDENN.ToLower.Contains("false") -> hier nun raus aus der schleife und True zurückgeben...
    4. If WASSDENN.ToLower.Contains("samstag") -> hier nun raus aus der schleife und Konvertiere(WASSDENN) zu Wochentag und diesen zurückgeben...
    5. Next For


    Ein "Select Case" ist in diesen Szenario eher angebracht und Wichtig ist der Sprungpunkt aus der Verzweigung bzw. Schleife.

    Wenn die Objekt/Wertetypen bekannt sind, kann das "aussieben" überschaubar sein.

    Es ist auch möglich mittels ".TryParse()" und "Try-Catch" zu arbeiten, ist aber nicht zu empfehlen.

    Wie @RodFromGermany schon erwähnte ist die Reihenfolge der Schlüssel.
    Ist der Typ ermittelt, dann nicht weiter Prüfen und raus aus der Nummer... hehe

    @ErfinderDesRades das mit dem TypeDescriptor.GetConverter(Type) muss ich mir mal genauer anschauen...
    "So Du Typ. Komm mal ran, an Zentimeter... Wie würdest Du dich den Beschreiben? ", sagte der Türsteher zum erstbesucher einer Diskothek bei Wanneeikel.

    Es gibt auch noch die Möglichkeit mittels RegEx die eingelesenen "Strings" als Typen durch Mustervergleich zu erkennen, und diese dann erst umzuwandeln (Type-Cast).

    Die Methode mit den RegEx ist nicht energieeffizient, aber sie ist sehr Präzise.

    c.u. Joshi aus HH
    Warum serialisierst Du die Daten nicht einfach, so ersparst Du Dir das ganze drum rum. JSON, bzw. XML würde sich anbieten, um die Daten direkt (also in der Datei) ändern zu können.

    VB.NET-Quellcode

    1. Imports Newtonsoft.Json
    2. Imports System.IO
    3. Public Class Form1
    4. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    5. Dim t As New TestClass() With {.BoolValue = False, .CheckstateValue = CheckState.Indeterminate, .StringValue = "test"}
    6. File.WriteAllText("props.txt", JsonConvert.SerializeObject(t))
    7. End Sub
    8. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    9. Dim json As String = File.ReadAllText("props.txt")
    10. Dim t As TestClass = JsonConvert.DeserializeObject(Of TestClass)(json)
    11. End Sub
    12. End Class
    13. Public Class TestClass
    14. Public Property StringValue As String
    15. Public Property CheckstateValue As CheckState
    16. Public Property BoolValue As Boolean
    17. End Class
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Vielen Dank für alle Vorschläge.

    Mein Problem ist, dass ich mit XML bislang nur gearbeitet habe, um datatables und datasets wegzuschreiben und zu lesen.
    Mir war nicht klar, dass ich einfach ganze klassen so weg schreiben kann.

    Ich arbeite leiber mit XML, da ich mich mit Jason gar nicht auskenne. Kann nur Sensoren über Jason auslesen.

    Mit xml lässt sich das ganze so einfach realisieren? Das wäre ja ein Traum.
    Über jason hatte ich schonmal etwas gelesen, mich jedoch nicht damit befasst. @SpaceyX Dein Beispiel oben ist ja mehr als vollständig.

    Könntest du mir auch die XML Variante nahelegen?
    Datasets haben ja z.B. die möglichkeit DS.WriteXML... Das ist ja selbsterklärend. Wie schreibe ich sowas denn für eine eigene Klasse? Was brauche ich an zusatztools? Da ich mitten drin stecke, wär ne Erklärung echt fett. :)
    ~Wir leben zwar alle unter dem gleichen Himmel, aber es haben nicht alle den gleichen Horizont~
    Hi.

    Ich benutze folgendes um die "Einstellungen" in der App zu speichern und einzulesen.

    VB.NET-Quellcode

    1. ReadOnly _settingsfilePath As String = AppDomain.CurrentDomain.BaseDirectory & "settings.xml"
    2. Private _appSettings As Settings
    3. Public Property AppSettings As Settings
    4. Get
    5. Return _appSettings
    6. End Get
    7. Set
    8. _appSettings = Value
    9. 'NotifyPropertyChanged("AppSettings")
    10. End Set
    11. End Property
    12. Sub ReadSettings()
    13. Dim fileExists As Boolean
    14. fileExists = File.Exists(_settingsfilePath)
    15. If fileExists Then
    16. AppSettings = DeSerialize (Of Settings)(_settingsfilePath) ' <--- ACHTUNG! Hier (Of deineKlasse) beachten...
    17. Else
    18. WriteSettings()
    19. End If
    20. End Sub
    21. Sub WriteSettings()
    22. Serialize(AppSettings, _settingsfilePath)
    23. End Sub
    24. Public Shared Function Serialize (Of T)(value As T, ByRef serializeXml As String) As Boolean
    25. If (value Is Nothing) Then
    26. Return False
    27. End If
    28. Try
    29. Dim xmlserializer = New XmlSerializer(GetType(T))
    30. Dim writer As StreamWriter = File.CreateText(serializeXml)
    31. xmlserializer.Serialize(writer, value)
    32. writer.Flush()
    33. writer.Close()
    34. Return True
    35. Catch ex As Exception
    36. Return False
    37. End Try
    38. End Function
    39. Public Shared Function DeSerialize (Of T)(ByRef deserializeXml As String) As T
    40. Dim dummy As T
    41. Dim xmlserializer = New XmlSerializer(GetType(T))
    42. Dim reader As StreamReader = File.OpenText(deserializeXml)
    43. dummy = CType(xmlserializer.Deserialize(reader), T)
    44. reader.Close()
    45. Return dummy
    46. End Function


    Um die Klassen "Serialisierbar" zu machen muss eine "dekoration" vorgenommen werden.

    Vor jeder Klasse einfach "<Serializable>" eine Zeile vor/über der Klassen definition einfügen.

    Das gilt auch für JSON-Serialisierungen...

    Folgendes ein Beispiel meiner "Settings.vb"

    VB.NET-Quellcode

    1. Namespace Models
    2. <Serializable>
    3. Public Class Settings
    4. Public Property LastTable As String
    5. Public Property CategoriesFilePath As String
    6. Public Property ImagesFilePath As String
    7. Public Property PagesFilePath As String
    8. Public Property ImagesCacheFolderPath As String
    9. End Class
    10. End NameSpace


    Das Resultat in form von XML.

    XML-Quellcode

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <Settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    3. <CategoriesFilePath>u:\Documents\Visual Studio 2015\Projects\CreativerseWIKIAEditor\CreativerseWIKIAEditor\bin\Debug\Categories.xml</CategoriesFilePath>
    4. <PagesFilePath>u:\Documents\Visual Studio 2015\Projects\CreativerseWIKIAEditor\CreativerseWIKIAEditor\bin\Debug\Pages.xml</PagesFilePath>
    5. <ImagesFilePath>u:\Documents\Visual Studio 2015\Projects\CreativerseWIKIAEditor\CreativerseWIKIAEditor\bin\Debug\Images.xml</ImagesFilePath>
    6. <ImagesCacheFolderPath>u:\Documents\Visual Studio 2015\Projects\CreativerseWIKIAEditor\CreativerseWIKIAEditor\bin\Debug\Cache\Images</ImagesCacheFolderPath>
    7. </Settings>


    Das ist eine generalisierte vorgehensweise, mit der alle Objekte serialisiert werden können.
    Listen und verschachtelte Objekte werden einfach serialisiert.

    Wenn das XML eine "definiertere" Schreibweise haben soll, kann mittels Deokration einfluss auf die Eigenschaften genommen werden.

    Hier mal ein Ignorant...

    VB.NET-Quellcode

    1. <XmlIgnoreAttribute>
    2. Public Property ImagesCacheFolderPath As String


    Für die Dekoration von Listelementen einfach hier hingehen und mal gucken...

    docs.microsoft.com/de-de/dotne…ute?view=netframework-4.8

    Das ist natürlich nicht der Weisheit letzer Kurzschluß...

    Ich hingegen brauche für die eigenen Projekte keine "Eigenschaften"-dekorationen, aber beim Austausch mit anderen, kann es nützlich sein.
    Somit schmeisse ich einfach was ich speichern will, als Objektinstanz in den "Serialize", und dann einmal im Texteditor der Wahl öffnen und "AHHH" machen...

    c.u Joshi aus Hamburg
    Dazu gibts im System.Xml.Serialization-Namespace die Klasse XmlSerializer

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.Xml.Serialization
    3. Public Class Form1
    4. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    5. Dim t As New TestClass() With {.BoolValue = False, .CheckstateValue = CheckState.Indeterminate, .StringValue = "test1"}
    6. Dim x As New XmlSerializer(GetType(TestClass))
    7. Using fS As New FileStream("props.xml", FileMode.Create, FileAccess.ReadWrite, FileShare.None)
    8. x.Serialize(fS, t)
    9. End Using
    10. End Sub
    11. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    12. If File.Exists("props.xml") Then
    13. Dim x As New XmlSerializer(GetType(TestClass))
    14. Dim t As TestClass = Nothing
    15. Using fS As New FileStream("props.xml", FileMode.Open, FileAccess.ReadWrite, FileShare.None)
    16. t = DirectCast(x.Deserialize(fS), TestClass)
    17. End Using
    18. End If
    19. End Sub
    20. End Class
    21. <Serializable()>
    22. Public Class TestClass
    23. Public Property StringValue As String
    24. Public Property CheckstateValue As CheckState
    25. Public Property BoolValue As Boolean
    26. End Class


    Sollte so gehen. Hab das lange nicht mehr benutzt. Wenn es um solche Dinge geht, nutze ich fast nur noch ausschließlich JSON. Solltest Du Dir bei Gelegenheit auch aneignen. Wie das erste Beispiel zeigt, ist es wesentlich einfacher, und mit weniger Codezeilen zu nutzen. Der Nachteil ist halt, dass man eine externe .dll mitliefern muss....
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    SpaceyX schrieb:

    JSON [...] Wie das erste Beispiel zeigt, ist es wesentlich einfacher
    Hmm - was ist an Json-Serialisierung einfacher als an Xml-Serialisierung?
    Ich sehe da vom Aufwand her keinen Unterschied, ob man nun den Newtonsoft.JsonSerializer nimmt oder den XmlSerializer.
    Json ist sogar ein Stück aufwändiger, weil das muss man sich erst besorgen, während der XmlSerializer Framework-OnBord ist.
    Aber vlt habich auch nur das "erste Beispiel" nicht gesehen - welches meinst du?
    Ich persönlich finde JSON einfacher zu lesen. XML hat mich seit jeher immer ein wenig irritiert. Zweitens meine ich, dass es ein bissl weniger Code ist, den man tippen muss. Drittens wird JSON so gut wie überall in der Webprogrammierung verwendet und es tut einem bestimmt gut, sich damit zu beschäftigen. In einigen anderen Sprachen ist JSON fester Bestandteil (XML womöglich auch, weiß ich jetzt nicht). Ich meine aber mal irgendwo gelesen zu haben, dass JSON durchaus auch in .NET zu den Boardmitteln gehört. Müsste ich jetzt nochmal nachguggn (was ich auch mache). Ich hab halt meine Vorlieben und die habe ich versucht, an den Mann zu bringen...

    @ErfinderDesRades

    Jo, ich hatte recht. JSON ist auch Bestandteil des Frameworks.... Zu finden in System.Web.Extensions.dll

    VB.NET-Quellcode

    1. Imports System.Web.Script.Serialization
    2. Public Class Form1
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. Dim t As New TestClass() With {.BoolValue = False, .CheckstateValue = CheckState.Indeterminate, .StringValue = "test1"}
    5. Dim j As New JavaScriptSerializer()
    6. Dim json As String = j.Serialize(t)
    7. Debug.Write(json)
    8. End Sub
    9. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    10. Dim json As String = "{""StringValue"":""test1"",""CheckstateValue"":2,""BoolValue"":false}"
    11. Dim j As New JavaScriptSerializer()
    12. Dim t As TestClass = j.Deserialize(Of TestClass)(json)
    13. Debug.Write(t.StringValue)
    14. End Sub
    15. End Class
    16. <Serializable()>
    17. Public Class TestClass
    18. Public Property StringValue As String
    19. Public Property CheckstateValue As CheckState
    20. Public Property BoolValue As Boolean
    21. End Class


    Newtonsoft.JSON ist halt so populär, dass es meist bevorzugt wird, obwohl die Handhabung, jetzt wo ich es selber mal probiert hab, die Gleiche ist.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

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

    :o Vielen Dank für diese ausführlichen Antworten. Ob XML oder Json ist ja dann eher Geschmackssache. Mir hilft es aber sehr gut weiter. Ich werde das ganze jetzt mal mit meiner Config Klasse ausprobieren. Mal sehen was ich raus bekomme. Vielen Dank!
    ~Wir leben zwar alle unter dem gleichen Himmel, aber es haben nicht alle den gleichen Horizont~