2011-10-26 6 views
9

Mam klasy:W jaki sposób deserializować XML do obiektu przy użyciu konstruktora, który pobiera XDocument?

public class MyClass 
{ 
    public MyClass(){} 
} 

Chciałbym, aby móc korzystać z XMLSeralizer deserializacji się XDocument bezpośrednio w konstruktorze tak:

public class MyClass 
{ 
    private XmlSerializer _s = new XmlSerializer(typeof(MyClass)); 

    public MyClass(){} 
    public MyClass(XDocument xd) 
    { 
     this = (MyClass)_s.Deserialize(xd.CreateReader()); 
    } 
} 

Tyle że nie wolno mi przypisać " to "w konstruktorze.

Czy to możliwe?

+0

Z jakiego powodu chcesz zrobić to w ten sposób? – Fischermaen

+0

Ponieważ dobrze byłoby utworzyć instancję klasy i po prostu nakarmić ją XDocumentem i ustawić w taki sposób. Są inne rozwiązania, ale wydaje mi się to najbardziej eleganckie ... Jestem otwarty na lepsze sugestie. –

+0

Nie możesz ustawić klasy, aby dane były do ​​niej serializowane, tworząc dla ciebie instancję? – Yatrix

Odpowiedz

26

Nie, to niemożliwe. Serializery tworzą obiekty podczas deserializacji. Już stworzyłeś obiekt. Zamiast tego podaj statyczną metodę konstruowania z XDocument.

public static MyClass FromXml (XDocument xd) 
{ 
    XmlSerializer s = new XmlSerializer(typeof(MyClass)); 
    return (MyClass)s.Deserialize(xd.CreateReader()); 
} 
+0

i jak zrobić lodówkę, gdy extraTypes (knownTypes) nie są znane podczas kompilacji? To jest złe, nie mamy nawet wstępnego callbacku, aby zainicjować coś przed rozpoczęciem deserializacji? –

6

Bardziej standardowe jest stosowanie metody obciążenia statycznego.

public class MyClass 
{ 
    public static MyClass Load(XDocument xDoc) 
    { 
     XmlSerializer _s = new XmlSerializer(typeof(MyClass)); 
     return (MyClass)_s.Deserialize(xDoc.CreateReader()); 
    } 
} 
3

Czy lepiej użyć jakiegoś zakładu, np .:

public static MyClass Create(XDocument xd) 
{ 
    XmlSerializer _s = new XmlSerializer(typeof(MyClass)); 
    return (MyClass)_s.Deserialize(xd.CreateReader()); 
} 
-1

Prosta odpowiedź na to pytanie brzmi: nie, nie możesz. Powodem jest to, że tworzysz obiekt, gdy deserializujesz.

Ale jeśli naprawdę nalegasz na możliwość, aby obiekt sam stworzył instancję, możesz użyć prywatnej statycznej zmiennej instancji, którą możesz wczytać wraz z obiektem, który uzyskasz po deserializacji. Pozostali członkowie publiczne powinny następnie działać na przykład (gdy nie jest zerowa, że ​​jest)

przykładem (z mojej głowy, więc istnieje niewielka szansa, że ​​nie jest całkowicie poprawne):

public class MyClass 
{ 
    private XmlSerializer _s = new XmlSerializer(typeof(MyClass)); 
    private static MyClass mInstance = null; 

    public MyClass() { /* initialization logic */ } 
    public MyClass(XDocument xd) 
    { 
     mInstance = (MyClass)_s.Deserialize(xd.CreateReader()); 
    } 

    public void DoSomething() 
    { 
    if (mInstance != null) 
     mInstance.DoSomething(); 
    else 
    { 
     // logic for DoSomething 
    } 

    } 
} 

Mam nadzieję, że to trochę wyjaśnia, ale nie przepadam za takim projektem. Myślę, że to sprawia, że ​​wszystko jest zbyt skomplikowane i wrażliwe na błędy.

+0

Zdajesz sobie sprawę, że każda klasa MyClass, którą stworzysz za pierwszym, zastąpi poprzednie wystąpienia statycznej mInstance? Następnie wszystkie instancowane obiekty MyClass będą używały tego samego obiektu w pamięci. – SamuelWarren

1

chciałem zrobić to samo i postanowił wykonać następujące czynności:

public class MyClass 
{ 
    public MyClass(){ 
    } 

    public MyClass(XDocument xd) 
    { 
     var t = typeof(MyClass); 
     var o = (MyClass)new XmlSerializer(t).Deserialize(xd.CreateReader()); 

     foreach (var property in t.GetProperties()) 
      property.SetValue(this, property.GetValue(o)); 
    } 
}