Entwickler-Ecke

IO, XML und Registry - Fehler bei XML-Serialisierung einer Klasse


derprogrammier69 - Mo 27.01.14 14:18
Titel: Fehler bei XML-Serialisierung einer Klasse
Hi, ich möchte meine Klasse PurchaseOrder serialisieren und es kommt leider die Fehlermeldung: "Eine nicht behandelte Ausnahme des Typs "System.InvalidOperationException" ist in System.Xml.dll aufgetreten.
Zusätzliche Informationen: Auf 'Finances.Program' kann aufgrund der Sicherheitsebene nicht zugegriffen werden. Nur öffentliche Typen können verarbeitet werden."
Ich verzweifle schon, habe auch mal probiert vor alle Klassen [Serializible] zu schreiben, das funktioniert leider auch nicht :( Bitte um schnelle Hilfe, vielen lieben Dank!


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Finances
{
    class Program
    {
        //-----------------------------------------------------------
        public class Address
        {
            String Name;
            String Street;
            String Zip;
            String City;

            //Konstruktor:
            public Address(String name, String street, String zip, String city) 
            {
                this.Name = name;
                this.Street = street;
                this.Zip = zip;
                this.City = city;
            }
        }

        //-----------------------------------------------------------
        public class OrderItem
        {
            String ItemName;
            String Description;
            decimal UnitPrice;
            int Quantity;

            //Konstruktor:
            public OrderItem(String itemname, String description, decimal unitprice, int quantity) 
            {
                this.ItemName = itemname;
                this.Description = description;
                this.UnitPrice = unitprice;
                this.Quantity = quantity;
            }

            //Property zur Berechnung des Gesamtpreises einer Artikelposition:
            public decimal LineTotal
            {
                get 
                {
                return this.UnitPrice * this.Quantity;
                }
            }

        }

        //-----------------------------------------------------------
        public class PurchaseOrder
        {
            Address ShipTo;
            String OrderDate;
            OrderItem[] OrderItems = new OrderItem[2]; //hier nur zum Testen 2 OrderItems im Array
            decimal ShipCost;

            //Konstruktor:
            public PurchaseOrder(Address shipto, String orderdate, OrderItem[] orderitems, decimal shipcost)
            {
                this.ShipTo = shipto;
                this.OrderDate = orderdate;
                this.OrderItems = orderitems;
                this.ShipCost = shipcost;
            }

            //Parameterloser Konstruktor (benötigt für Serialisierung):
            public PurchaseOrder() {}

            //Property#1 - Summe aller OrderItems im Array
            public decimal SubTotal
            {
                get
                {
                    decimal subtotal = 0;
                    foreach(OrderItem oitem in OrderItems)
                    {
                        subtotal += oitem.LineTotal;
                    }
                    return subtotal;
                }
            }

            //Property#2 - SubTotal (s. oben) + ShipCost
            public decimal TotalCost
            {
                get
                {
                    decimal subtotal = 0;
                    foreach (OrderItem oitem in OrderItems)
                    {
                        subtotal += oitem.LineTotal;
                    }
                    subtotal += this.ShipCost; //einziger Unterschied zu Property#1
                    return subtotal;
                }
            }

            //Methode zur Serialisierung:
            public void ExportToXML(string filename)
            {
                XmlSerializer s = new XmlSerializer(typeof(PurchaseOrder)); //hierfür: "using System.Xml.Serialization"
                TextWriter writer = new StreamWriter(filename); //hierfür: "using System.IO"
                s.Serialize(writer, this);
                writer.Close();
            }
        }

        //-----------------------------------------------------------
        static void Main(string[] args)
        {
            // Objekte initialisieren:
            Address adresse = new Address("Max Mustermann""Musterstr. 6""66666""Musterhausen");

            OrderItem[] oitemarray = new OrderItem[2];
            oitemarray[0] = new OrderItem("Playstation 4""Beste Konsole zur Zeit auf dem Markt."4991);
            oitemarray[1] = new OrderItem("PS4 Controller""Echt ergonometrisch."592);

            PurchaseOrder bestellung = new PurchaseOrder(adresse, "01.01.2014", oitemarray, 5);

            bestellung.ExportToXML("Test.xml");


            //Pressanykey-Block:
#region Press any key...
#if DEBUG
            Console.WriteLine("Press any key to close...");
            Console.ReadLine();
#endif
#endregion
        }
    }
}


Christian S. - Mo 27.01.14 14:22

Hallo und :welcome:!

Deine Klassen sind ja alle in der Klasse "Program" verschachtelt (warum eigentlich?) und die ist nicht als public deklariert. Daher kann der Serializer nicht drauf zugreifen.

Viele Grüße
Christian


//edit: Ohne öffentliche, schreibbare Properties wird Dir die Serialisierung auch nicht viel bringen ;)


derprogrammier69 - Mo 27.01.14 14:36

Hi,
vielen Dank für die schnelle Antwort :)
Endlich funktioniert der Serialisierer ohne Fehlermeldung!
Die unübliche/ untstrukturierte Form des Quellcodes resultiert daraus, da es sich um eine Aufgabe aus einer Vorlesung hält, und alles so vorgegeben war :)

Leider gibt es noch ein Problemchen:
Das XML-File ausgegeben sind nun folgendermaßen aus:
<?xml version="1.0" encoding="UTF-8"?>
<PurchaseOrder xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>

-> Mehr steht da nicht, ich möchte aber ja alle Attributbelegungen/ Properties/ usw. der angelegten Objekte in dem File haben, was habe ich falsch gemacht?


VIELEN DANK, ECHT


Ralf Jansen - Mo 27.01.14 14:41

Der XMLSerializer serialisiert alle öffentlichen (public) Felder und Properties. Wieviele öffentliche Felder/Properties hast du?
Ich würde dir empfehlen immer die Sichtbarkeiten an Elemente dranzuschreiben auch wenn es sowas wie Defaultsichtbarkeiten gibt.


derprogrammier69 - Mo 27.01.14 14:45

Hi,
es sind schon alle Properties/ Felder auf public gesetzt (s. auch oben den Quellcode).
Liegt es vielleicht an dem parameterlosen Konstruktor von der Klasse (wurde von VS12 dazu gezwungen, diesen noch zu implementieren)?
MFG Jens

*EDIT: habe jetzt auch mal das XML-File wieder gelöscht und neu schreiben lassen (um diesen Fehler auszuschliessen), es klappt leider immer noch nicht


Christian S. - Mo 27.01.14 15:16

user profile iconderprogrammier69 hat folgendes geschrieben Zum zitierten Posting springen:
es sind schon alle Properties/ Felder auf public gesetzt (s. auch oben den Quellcode).

Deine Felder haben keinen Modifier davor und sind somit nicht public. Deine Properties sind zwar public, aber read-only. ;-)


derprogrammier69 - Mo 27.01.14 15:25

Hi, danke.
Habe gedacht wenn die Klasse public wäre, wären es die Felder automatisch auch.
Habe jetzt alle Felder auf public gesetzt, und jetzt kommt wieder eine andere Fehlermeldung :(
"Eine nicht behandelte Ausnahme des Typs "System.InvalidOperationException" ist in System.Xml.dll aufgetreten.
Zusätzliche Informationen: Fehler beim Reflektieren des Typs 'Finances.Program.PurchaseOrder'.":


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
public class Address
        {
            public String Name;
            public String Street;
            public String Zip;
            public String City;...

public class OrderItem
        {
            public String ItemName;
            public String Description;
            public decimal UnitPrice;
            public int Quantity;...

public class PurchaseOrder
        {
            public Address ShipTo;
            public String OrderDate;
            public OrderItem[] OrderItems = new OrderItem[2]; //hier nur zum Testen 2 OrderItems im Array
            public decimal ShipCost;



Vielen Dank, wir sind auf dem richtigen Weg :) Hoffe wir schaffen es (ist sehr wichtig für meine kommende Klausur)...

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt


Christian S. - Mo 27.01.14 15:28

Ich vermute mal, Du musst noch Address und OrderItem jeweils einen parameterlosen Konstruktor verpassen, weil die ja auch serialisiert werden.


derprogrammier69 - Mo 27.01.14 15:34

Hi,
ich bedanke mich hiermit für eure schnelle und kompetente Mitarbeit!
Diesem Forum bleibe ich treu :) Daumen hoch an alle! Jetzt hat es geklappt!!!!


Hier die Ausgabe (evtl. für ijemanden iwann hilfreich):

XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
<?xml version="1.0" encoding="utf-8"?>
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ShipTo>
    <Name>Max Mustermann</Name>
    <Street>Musterstr. 6</Street>
    <Zip>66666</Zip>
    <City>Musterhausen</City>
  </ShipTo>
  <OrderDate>01.01.2014</OrderDate>
  <OrderItems>
    <OrderItem>
      <ItemName>Playstation 4</ItemName>
      <Description>Beste Konsole zur Zeit auf dem Markt.</Description>
      <UnitPrice>499</UnitPrice>
      <Quantity>1</Quantity>
    </OrderItem>
    <OrderItem>
      <ItemName>PS4 Controller</ItemName>
      <Description>Echt ergonometrisch.</Description>
      <UnitPrice>59</UnitPrice>
      <Quantity>2</Quantity>
    </OrderItem>
  </OrderItems>
  <ShipCost>5</ShipCost>
</PurchaseOrder>


Moderiert von user profile iconChristian S.: XML-Tags hinzugefügt