2016-07-14 1 views
0

Ma classe ressemble à ceci:C# XML objet désérialiseur ne pas construire correctement

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) 
    } 
} 

Cela fonctionne bien quand j'instancier mon propre objet myClass avec & paramètres b, mais le désérialiseur n'appeler le constructeur de paramaterless. Comment initialiser C sans créer une autre méthode et l'appeler après la désérialisation?

+0

Il y a des événements de sérialisation pour ce qui sérialiseur vous utilisez chacun est différent – Jim

+0

'System.Xml.Serialization.XmlSerializer' –

+0

Quand deseralized il devrait ramener les valeurs de A, B et C les mêmes valeurs quand il a été sérialisé. Donc, ils étaient 1, 2 et 3 lorsqu'ils ont été sauvés, ils devraient à nouveau être 1, 2 et 3 après désérialisé. Par conséquent, il n'y a rien de mal avec votre code. –

Répondre

0

désérialisation va juste remplir les variables - toute autre logique nécessaire pour instancier l'objet doit être exécuté par le programme, et non désérialiseur. Essayez quelque chose comme ceci:

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) 
    } 
} 

Ou mieux encore:

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: Si les variables doivent être définies avant que la logique est exécutée, vous pouvez créer une instance vide de la classe puis définissez les variables utilisant une méthode d'aide qui prend XML comme une entrée. Voir la réponse suivante pour un exemple: When is the class constructor called while deserialising using XmlSerializer.Deserialize?

+0

J'ai essayé votre première méthode, mais lorsque le constructeur sans paramètre est appelé, A et B ne sont pas initialisés, donc 'GetStuffReady()' échoue. Je n'ai pas assez de données lors d'une instanciation sans paramètre pour effectuer le 'Stuff' nécessaire. De plus, le 'Stuff' implique plus qu'un simple' get', donc c'est aussi disponible. –

+0

pourquoi ne pas simplement effectuer l'opération coûteuse une fois, et mémoize le résultat. faire le calcul la première fois quel que soit le constructeur. – Jim

+0

Vous avez raison: la logique est exécutée en premier, puis les valeurs sont définies. Vous pouvez essayer de créer une instance vide, puis définir les variables à l'aide d'une méthode d'assistance qui prend XML comme entrée ... Toute logique supplémentaire peut se produire plus tard dans la même méthode. Voir cette réponse: http://stackoverflow.com/questions/5198431/when-is-the-class-constructor-called-while-deserialising-using-xmlserializer-des –

0

Vous pouvez modifier simplement le getter C comme:

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

J'apprécie la suggestion, mais je fais plus de 'a + b', et ces calculs n'appartiennent pas à' get'. J'ai seulement paraphrasé le code pour faire passer l'idée. –

0

Si vous utilisez le binaire formatter régulier, puis:

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

Pour les XmlSerializer, les événements ne sont pas pris en charge. Vous pouvez implémenter IXmlSerializable, mais ce n'est pas trivial.

Pour DataContractSerializer (qui sérialise au format XML), vous pouvez essayer:

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

Il y a une réponse ici pour XmlSerializer mais il faut héritant par défaut.
How do you find out when you've been loaded via XML Serialization?