Laden...

Eine Klasse lässt sich nicht Serialisieren

Erstellt von jok3r89 vor 6 Jahren Letzter Beitrag vor 6 Jahren 2.787 Views
J
jok3r89 Themenstarter:in
70 Beiträge seit 2017
vor 6 Jahren
Eine Klasse lässt sich nicht Serialisieren

Hallo,
ich kann meine Klasse nicht Serialisieren, woran kann das liegen oder stoße ich an die Grenzen ?



    [XmlRoot("DBModels"), Serializable()]
    public class DBModel
    {   //databas
        [XmlElement("DB")]
        public List<DB> db = new List<DB>();
    }

    public class DB
    {
        [XmlAttribute("name")]
        public string dbName { get; set; }
        [XmlElement("tag")]
        public S7Consts.S7Tag param= new S7Consts.S7Tag { DBNumber = 0,
                                                        Area = 0,
                                                        Start =0,
                                                        Elements = 0,
                                                        WordLen =0 };
        
        private enum DataTyp
        {   
            [XmlEnum("1")]
            S7_BOOL,
            [XmlEnum("2")]
            S7_SINT,
            [XmlEnum("3")]
            S7_INT,
            [XmlEnum("4")]
            S7_DINT,
            [XmlEnum("5")]
            S7_LINT,
            [XmlEnum("6")]
            S7_USINT,
            [XmlEnum("7")]
            S7_UINT
        }
        
        [XmlAttribute("readArea")]
        public List<Tuple<int, int>> Read { get; set; }
        [XmlAttribute("writeArea")]
        public List<Tuple<int, int>> Write { get; set; }
    }
 public void DBModelSerializer(DBModel model)
        {
            #region Save the object

            // Create a new XmlSerializer instance with the type of the test class
            XmlSerializer SerializerObj = new XmlSerializer(typeof(DBModel));

            // Create a new file stream to write the serialized object to a file
            string path = Path.Combine(Environment.CurrentDirectory, @"Data\", "DBModel.xml");

            if (!System.IO.File.Exists(path))
            {
                System.IO.Directory.CreateDirectory(@"Data\");
            }

            using (TextWriter WriteFileStream = new StreamWriter(path))
            {
                SerializerObj.Serialize(WriteFileStream, model);
                WriteFileStream.Close();
            }
            #endregion
        }

Habt ihr noch ideen?
Gruß

16.825 Beiträge seit 2008
vor 6 Jahren

Alle .NET Serializer brauchen einen parameterlosen Constructor. Sowas hat ein Tuple aber nicht, also kann es auch nicht serialisiert werden.
Das sollte Dir aber auch Deine Exception, die Du hier leider nicht genannt hast (bitte beachte [Hinweis] Wie poste ich richtig? Punkt 5), gesagt haben. Hast Du nach dieser denn vorher mal recherchiert?

Musst Dir was anderes bauen. Oder besser: was ordentliches verwenden wie eine eigene Klasse und kein Tuple.

PS: das Abspeichern Deiner XML wird so ohne Adminrechte an einem PC nicht funktionieren.
Ein normaler Benutzer hat keine Schreibrechte im Programmverzeichnis (und ich geh mal davon aus, dass da Deine Anwendung liegen wird).

J
jok3r89 Themenstarter:in
70 Beiträge seit 2017
vor 6 Jahren

Ich hätte es nochmals versucht, wenn ich es richtig verstanden habe sollte es nach dem hier aussehen ->


    public class DB
    {
        [XmlAttribute("name")]
        public string dbName { get; set; }
        [XmlElement("tag")]
        public S7Consts.S7Tag param = new S7Consts.S7Tag { DBNumber = 0,
            Area = 0,
            Start = 0,
            Elements = 0,
            WordLen = 0 };

        [XmlAttribute("read")]
        public List<S7Var> Read;
        [XmlAttribute("write")]
        public List<S7Var> Write;

    }

    public class S7Var
    {
        public int pos;
        public DataTyps typ;
    }

    public enum DataTyps
    {
        [XmlEnum("1")]
        S7_BOOL=1,
        [XmlEnum("2")]
        S7_SINT,
        [XmlEnum("3")]
        S7_INT,
        [XmlEnum("4")]
        S7_DINT,
        [XmlEnum("5")]
        S7_LINT,
        [XmlEnum("6")]
        S7_USINT,
        [XmlEnum("7")]
        S7_UINT
    }

Was ich zurück bekomme ist
"
'System.InvalidOperationException' occurred in System.Xml.dll

Additional information: Fehler beim Reflektieren des Typs 'Snap7_PLC.DBModel'."
Zu meiner Schande muss ich gestehen nein ich habs nicht genauer betrachtet aber ich muss mich damit mal mehr beschäftigen ich bin in C# noch ein Anfänger.
Gruß

J
jok3r89 Themenstarter:in
70 Beiträge seit 2017
vor 6 Jahren

Kurz nach dem letzten Beitrag habe ich eine Lösung gefunden die scheinbar jetzt erst mal funktioniert

    [XmlRoot("DBModels"), Serializable()]
    public class DBModel
    {   //databas
        [XmlElement("DB")]
        public List<DB> db { get; set; }
    }

    public class DB
    {
        [XmlAttribute("name")]
        public string dbName { get; set; }
        [XmlElement("tag")]
        public S7Consts.S7Tag param = new S7Consts.S7Tag { DBNumber = 0,
            Area = 0,
            Start = 0,
            Elements = 0,
            WordLen = 0 };

 //       [XmlAttribute("read")]
          public List<S7Var> Read { get; set; }
 //       [XmlAttribute("write")]
          public List<S7Var> Write { get; set; }

    }

    public class S7Var
    {
        public int posm { get; set; }
        public DataTyps typ { get; set; }
    }
    public enum DataTyps
    {
        [XmlEnum("1")]
        S7_BOOL=1,
        [XmlEnum("2")]
        S7_SINT,
        [XmlEnum("3")]
        S7_INT,
        [XmlEnum("4")]
        S7_DINT,
        [XmlEnum("5")]
        S7_LINT,
        [XmlEnum("6")]
        S7_USINT,
        [XmlEnum("7")]
        S7_UINT
    }

Aber wieso ist das so? Gruß

2.298 Beiträge seit 2010
vor 6 Jahren

Aber wieso ist das so?

Worauf genau beziehst du dich mit der Frage?

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

4.938 Beiträge seit 2008
vor 6 Jahren

Du meinst die Änderung


// [XmlAttribute("read")]
public List<S7Var> Read { get; set; }
// [XmlAttribute("write")]
public List<S7Var> Write { get; set; }

?
Der XmlSerializer serialisiert nur Eigenschaften (properties), keine Felder (members). Und die Fehlermeldung kam, weil du vorher explizit diese Felder mit dem XmlAttribute versehen hattest.

Edit: Gleiches gilt daher auch für die Änderung bei S7Var.

J
jok3r89 Themenstarter:in
70 Beiträge seit 2017
vor 6 Jahren

Also erst mal vielen Dank für die Antwort, von Feldern und Properties wird ja nicht in der Sprache gesprochen und mir ist das auch noch ein wenig fern....

Wieso ist jetzt das jetzt ein Feld ->


// [XmlAttribute("read")]
public List<S7Var> Read { get; set; }
// [XmlAttribute("write")]
public List<S7Var> Write { get; set; }

In C# hab ich des öfteren schon sowas gelesen hat es was damit zum tun?


   private int _alter; 
   public int alter 
   { 
      get { return _alter; } 
      set { _alter = value; } 
   } 

Was ich gemeint hatte ist der Ausdruck


// [XmlAttribute("write")]

Wenn ich es ausklammere gehts wenn nicht gehts nicht. Der Ausdruck(ich hab noch keine namen dafür wie man das nennt) sagt doch nur aus das mein Attribute eben write heißt ich sehe das eher als Option für den XmlSerializer

J
jok3r89 Themenstarter:in
70 Beiträge seit 2017
vor 6 Jahren

Ich bin in dem Punkt gerade auf was gestoßen und das hat wohl mit den Feldern und Eigenschaften zu tun.



        [XmlAttribute("read")]
        private List<S7Var> _Read;
        [XmlAttribute("write")]
        private List<S7Var> _Write;

        [XmlIgnore]
        public List<S7Var> Read {get { return _Read;  }
                                set { _Read = value; }}
        [XmlIgnore]
        public List<S7Var> Write { get { return _Write;}
                                   set { _Write = value; }}

Diese Lösung funktioniert dann wieder.

16.825 Beiträge seit 2008
vor 6 Jahren

Das ist aber absoluter Käse.

Wieso nicht einfach


        [XmlElement("read")]
        public List<S7Var> Read {get;set;}
        [XmlElement("write")]
        public List<S7Var> Write {get;set;}

Aber ma ganz ehrlich: willst Du Dich nicht einfach mal ordentlich in das Thema einlesen, statt hier mehr oder minder vieles nach dem langwierigen Try-And-Error Prinzip abzuklopfen?
Die letzten Threads hätten sich nach einem ordentlichen Tutorial gar nicht ergeben. So würdest Du auch viel strukturierter und schneller ans Ziel kommen, was ja der eigentliche Zweck wäre...

5.658 Beiträge seit 2006
vor 6 Jahren

        public List<S7Var> Read {get;set;}
        public List<S7Var> Write {get;set;}

Das würde ausreichen. Man kann ja eine Liste eh nicht in einem XML-Attribut speichern, dafür benötigt man ein XML-Element. Siehe XmlAttribute. Wenn man den Namen des Elements ändern möchte, dann mit XmlElement.

Zum Einstieg gibt es auch Anleitungen: Introducing Xml Serialization.

Weeks of programming can save you hours of planning