| Autor |
Beitrag |
BlackMatrix
      
Beiträge: 243
Erhaltene Danke: 1
|
Verfasst: Di 18.09.12 20:00
Hallo,
der Nutzer meines Programms kann im DataGridView Nutzerinformationen eingeben, wie z.B. Name, Vorname, Adresse, etc. Auf Basis dieser Nutzerinformationen kann er Accounts erstellen. Es können mehrere Accounts mit gleichen Nutzerinformationen erstellt werden. Die Nutzerinformationen ist eine Property der Accountklasse.
Bisher habe ich die Nutzerinformationen und die Accounts einzeln serialisiert. Das hat dazu geführt, dass die Nutzerinformationen nicht mehr als Verweis behandelt werden, somit hat das Abändern der Nutzerinformationen nicht automatisch dazu geführt, dass die Nutzerinformationen dieser Accounts abgeändert wurden.
Nun möchte ich gerne, dass sowohl die Accountdaten als auch die Nutzerinformationen serialisiert werden und die Verweise erhalten bleiben. Ist dies schon bei der Serialisierung möglich oder funktioniert das nur, indem ich das INotifyPropertyChanged Ereignis abboniere und alle Accounts durchgehe und abändere?
Ich hoffe es ist soweit verständlich.
MfG BlackMatrix
P.S: Ich habe kurz was geschrieben um es zu verdeutlichen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| [Serializable] class UserInformation { public string Name { get; set; } }
[Serializable] class Account { public UserInformation UserInformation { get; set; } } |
So serialisiere ich:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| var userInformation = new UserInformation (); userInformation.Name = "Hans";
var account1 = new Account(); account1.UserInformation = userInformation; var account2 = new Account(); account2.UserInformation = userInformation ;
var accounts = new List<Account> { account1, account2 };
var formatter = new BinaryFormatter(); using (FileStream stream = new FileStream("accounts.dat", FileMode.Create)) formatter.Serialize(stream, accounts); using (FileStream stream = new FileStream("userInformation.dat", FileMode.Create)) formatter.Serialize(stream, userInformation); |
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| List<Account> accounts; UserInformation userInformation ; BinaryFormatter formatter = new BinaryFormatter(); using (FileStream stream = new FileStream("accounts.dat", FileMode.Open)) accounts = (List<Account>)formatter.Deserialize(stream); using (FileStream stream = new FileStream("userInformation.dat", FileMode.Open)) userInformation = (User)formatter.Deserialize(stream);
userInformation.Name = "Sven"; |
Zuletzt bearbeitet von BlackMatrix am Di 18.09.12 21:17, insgesamt 2-mal bearbeitet
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Di 18.09.12 21:02
| Zitat: | | Nun möchte ich gerne, dass sowohl die Accountdaten als auch die Nutzerinformationen serialisiert werden und die Verweise erhalten bleiben |
Dann musst du sie auch in einem Rutsch serialisieren. Nach dem Serialisieren/Deserialisieren hat das System kein Wissen mehr das die in accounts.dat und userInformation.dat zufällig gleichen UserInformation Klassen mal die gleichen Instanzen waren. Wofür ist die Serialisierung von UserInformation überhaupt? Die Instanz steckt doch schon implizit in der Serialisierung der Accountsliste. Wenn du also zum Beispiel nach dem Deserialisieren accounts[0].UserInformation.Name = "Sven"; sollte eigentlich genau das passieren was du erhoffst.
|
|
BlackMatrix 
      
Beiträge: 243
Erhaltene Danke: 1
|
Verfasst: Di 18.09.12 21:13
Ich möchte gerne in einem extra DGV angezeigt bekommen, welche UserInformationen bereits angelegt wurden und diese ggf. durch den Benutzer editierbar machen.
Also wie am besten vorgehen? Nur die Accounts serialisieren und dann beim Start prüfen, wieviele verschiedene UserInformationen darin enthalten sind um diese dann im DGV anzuzeigen?
Ich möchte die UserInformationen an einer zentralen Stelle, durch den Benutzer, anzeig- und änderbar machen.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Di 18.09.12 22:15
Packe die Liste der Accounts und die Liste der UserInformation in eine Klasse und serialisiere diese. Da sie dann in einem gemeinsamen Serialisierungsvorgang sind sollten die Referenzen richtig erhalten bleiben.
|
|
Palladin007
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Di 18.09.12 22:45
So wie ich das verstehe, möchte er die User-Informationen gesondert speichern und nicht in der selben Datei, wie der Rest, oder?
In dem Fall wüsste ich nicht, wie man das direkt machen lassen könnte.
Was ich aber versuchen würde, ist folgendes:
Und zwar würde ich dann über XML gehen und in der Account-Klasse IXmlSerializable implementieren.
Das hat den Sinn, dass ich direkt angeben kann, was wie serialisiert wird. Ich gehe dann überall normal vor, mache bei den User-Informationen aber eine Ausnahme.
Die serialisiere ich extra, speichere das als Datei ab und schreibe in Account an die Stelle, wo die Infos eigentlich sein sollten, den Datei-Namen hin.
So sind die Daten getrennt verfügbar.
Bei der deserialisierung gehe ich auch ganz normal vor, nur bei den Infos lese ich die Datei aus, deserialisiere die extra und lege die resultierende Referenz dann im Account ab.
Solange du das alles intern in der Account-Klasse machen lässt, brauchst du dich nicht drum kümmern und die Infos sind brav als Referenz im Account hinterlegt, werden aber trotzdem getrennt gespeichert.
Das hat zwar den Nachteil, dass der Name nicht geändert werden darf, aber was besseres fällt mir nicht ein
Vielleicht kann man ja auch den Umweg über eine nicht änderbare Eigenschaft der Datei gehen, wo dann ein fester Code drin steht, nach dem dann im entsprechenden Ordner gesucht wird. Auf diese Weise kann man dann halt die Informations-XML bestimmen. Nur hab ich keine Ahnung, wie das geht. Hab ja so schon lange genug gebraucht um simple Informationen wie Interpret aus einer mp3-Datei lesen zu können.
Wenn es binäre Serialisierung sein soll, dann würde ich das ähnlich versuchen.
Und zwar die Info-Referenz in einen Stream serialisieren lassen, diese Referenz bei der Serialisierung des Accounts blockieren und dann mit einer weiteren Eigenschaft den Datei-Namen speichern und serialisieren.
Das braucht eine neue Eigenschaft aber ein besserer Weg fällt mir nicht ein.
Auch ist das, denke ich, in deinem Fall kein Problem, denn dann kannst du dem Nutzer gleich anzeigen lassen, wo die Info-Datei liegt, was ja auch nicht schlimm ist, schließlich soll er sie gesondert anpassen dürfen.
|
|
BlackMatrix 
      
Beiträge: 243
Erhaltene Danke: 1
|
Verfasst: Mi 19.09.12 12:00
Ich danke euch beiden.
@Palladin700: Die Daten brauchen nicht extra in seperate Dateien gepackt werden.
Ich werde es so machen, wie Ralf Jansen vorgeschlagen hat. Ich werde einfach alle Daten, die sich in meinem Programm ansammeln in die neue Klasse ApplicationData packen und dann beim deserialisieren an die Controls binden.
Ich hatte mir auch überlegt eine Datenbank anzulegen und mittels NHibernate meine Daten in eine SQLite Datenbank zu packen. Was mich auf diesem Wege interessieren würde, ab wann sollte man denn Datenbanken der (De-)Serialisierung vorziehen?
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 19.09.12 12:17
Serialisieren/Deserialisierung legt dich eigentlich auf einen Benutzer/Anwendung fest. Solange das dann noch von der Datenmenge ok ist (du liest die ja dann immer komplett in den Speicher) kann man das so machen.
Du solltest aber auch mal probieren was passiert wenn du dein Datenmodell änderst/ergänzt. Das lesen der alten binären Daten im alten Format wird dann höchstwahrscheinlich problematisch. Ein Datenbankmodell mit dem ändern/verbessern der Anwendung nachzuziehen sollte wesentlich einfacher auszuprogrammieren sein.
|
|
|