2016-07-14 2 views
0

Meine Klasse sieht wie folgt aus:C# XML Deserializer nicht konstruieren Objekt richtig

public class MyClass 
{ 
    private void MyClass() { } //just to satisfy the XML serializer 
    public void MyClass(int a, int b) 
    { 
     A = a; 
     B = b; 
     C = a + b; 
    } 
    public int A { get; set; } 
    public int B { get; set; } 
    public int C { get; private set; } //private set is only to 
             //satisfy the XML Serializer 
    public void DoSomeMath() 
    { 
     Console.WriteLine("{0} + {1} = {2}\n", A, B, C) 
    } 
} 

Das funktioniert gut, wenn ich mein eigenes myClass Objekt mit & b Parameter instanziiert, aber der Deserializer nur den paramaterless Konstruktor aufrufen. Wie initialisiere ich C, ohne eine andere Methode zu erstellen und nach der Deserialisierung aufzurufen?

+0

Es gibt Serialisierung Ereignisse für diese die Serializer sind Sie jedes mit unterschiedlichen ist – Jim

+0

'System.Xml.Serialization.XmlSerializer' –

+0

Wenn deseralized sollte die Werte von A, B und C als die gleichen Werte zurückbringen als es serialisiert wurde. Sie waren also 1, 2 und 3, wenn sie gespeichert wurden, sollten sie nach der Deserialisierung wieder 1, 2 und 3 sein. Daher ist mit Ihrem Code nichts falsch. –

Antwort

0

Deserialisieren werden nur die Variablen füllen - andere Logik erforderlich das Objekt instanziiert muss durch das Programm ausgeführt werden, nicht die Deserializer. Probieren Sie etwas wie folgt aus:

public class MyClass 
{ 
    private void MyClass() // NOT just to satisfy the XML serializer 
    { 
     GetStuffReady(); 
    } 

    public void MyClass(int a, int b) 
    { 
     A = a; 
     B = b; 
     GetStuffReady(); 
    } 
    public int A { get; set; } 
    public int B { get; set; } 
    public int C { get; private set; } 

    public void GetStuffReady() 
    { 
     C = A + B; 
    } 

    public void DoSomeMath() 
    { 
     Console.WriteLine("{0} + {1} = {2}\n", A, B, C) 
    } 
} 

Oder noch besser:

public class MyClass 
{ 
     private void MyClass() { } //just to satisfy the XML serializer 
     public void MyClass(int a, int b) 
     { 
      A = a; 
      B = b; 
     } 
     public int A { get; set; } 
     public int B { get; set; } 
     public int C 
     { 
      get 
      { 
       return A + B; 
      } 
      set { } 
     } 
     public void DoSomeMath() 
     { 
      Console.WriteLine("{0} + {1} = {2}\n", A, B, C) 
     } 
    } 

EDIT: Wenn die Variablen müssen gesetzt werden, bevor die Logik ausgeführt wird, können Sie eine leere Instanz der Klasse erstellen und dann eingestellt Die Variablen verwenden eine Hilfsmethode, die XML als Eingabe verwendet. Siehe folgende Antwort für ein Beispiel: When is the class constructor called while deserialising using XmlSerializer.Deserialize?

+0

Ich habe Ihre erste Methode versucht, aber wenn der parameterlose Konstruktor aufgerufen wird, sind A und B nicht initialisiert, so dass 'GetStuffReady()' fehlschlägt. Ich habe nicht genug Daten zum Zeitpunkt einer parameterlosen Instanziierung, um das notwendige 'Stuff' durchzuführen. Außerdem beinhaltet das 'Stuff' mehr als nur ein' Get', also ist es auch so. –

+0

warum führen Sie die teure Operation nicht einfach einmal durch und merken Sie sich das Ergebnis. Mach die Berechnung das erste Mal unabhängig vom Konstruktor. – Jim

+0

Sie haben Recht - die Logik wird zuerst ausgeführt und dann werden die Werte gesetzt. Sie könnten versuchen, eine leere Instanz zu erstellen und dann die Variablen mithilfe einer Hilfsmethode festzulegen, die XML als Eingabe verwendet ... Jede weitere Logik könnte später in derselben Methode auftreten. Siehe diese Antwort: http://stackoverflow.com/questions/5198431/when-is-the-class-constructor-called-while-deserialising-using-xmlserializer-des –

0

Sie können einfach die Getter für C ändern wie:

public int C { get { return this.A + this.B; }} 
+0

Ich schätze den Vorschlag, aber ich mache mehr als "a + b", und diese Berechnungen gehören nicht zu einem "Get". Ich habe den Code nur paraphrasiert, um die Idee zu vermitteln. –

0

Wenn Sie das regelmäßige binäre Formatierungsprogramm verwenden, dann:

[OnDeserialized] 
public void DoSomeMath() 
{ 
    Console.WriteLine("{0} + {1} = {2}\n", A, B, C) 
} 

Für die XmlSerializer, Ereignisse werden nicht unterstützt. Sie könnten IXmlSerializable implementieren, aber es ist nicht trivial.

Für DataContractSerializer (die XML serialisiert) Sie könnten versuchen:

[OnDeserializing] 
public void OnDeserializing(StreamingContext context) 
{ 
    ... // logic here. 
} 

Es gibt eine Antwort hier XmlSerializer aber es erfordert den Standard ein vererben.
How do you find out when you've been loaded via XML Serialization?