2011-10-26 16 views
9

tengo una clase:¿Cómo deserializo XML en un objeto usando un constructor que toma un XDocument?

public class MyClass 
{ 
    public MyClass(){} 
} 

Me gustaría ser capaz de utilizar un XMLSeralizer deserializar un XDocument directamente en el constructor de este modo:

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

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

Excepto que no se me permite asignar a " esto "dentro del constructor".

¿Esto es posible?

+0

¿Por qué razón desea hacerlo así? – Fischermaen

+0

Porque sería bueno crear una instancia de la clase y solo darle un XDocument y hacer que se configure así. Hay otras soluciones, pero esto me parece más elegante ... Estoy abierto a mejores sugerencias. –

+0

¿No puede configurar la clase para que tenga datos serializados en ella, creando así la instancia para usted? – Yatrix

Respuesta

26

No, no es posible. Los serializadores crean objetos cuando se deserializan. Ya has creado un objeto. En su lugar, proporcione un método estático para construir desde un XDocument.

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

y cómo se supone que debes hacer el frigorífico cuando no se conocen los extraTypes (knownTypes) en el momento de la compilación. Esto es malo, ni siquiera tenemos una devolución de llamada previa para iniciar cosas antes de comenzar a deserializar? –

6

Es más estándar usar un método de carga estática.

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

Es mejor utilizar algún tipo de fábrica, por ejemplo .:

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

La respuesta simple a su pregunta es no, no se puede. Por lo tanto, la razón es que creas un objeto cuando te deserializas.

Pero si realmente insistes en la posibilidad de que un objeto se instaure por así decirlo, puedes usar una variable de instancia estática privada que puedes cargar con el objeto que obtienes después de la deserialización. Los otros miembros del público deben luego trabajar en la instancia (cuando no es nula de que es)

un ejemplo (de la cabeza, por lo que hay una ligera posibilidad de que no es del todo correcto):

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 
    } 

    } 
} 

Espero que esto lo deje un poco claro, pero no me gusta ese diseño. Creo que lo hace demasiado complejo y sensible a los errores.

+0

¿Se da cuenta de que cada MyClass que crea una instancia después de la primera reemplazará las instancias previas de la mInstancia estática? Entonces todos los objetos MyClass instanciados usarán el mismo objeto en la memoria. – SamuelWarren

1

que quería hacer lo mismo y decidió hacer lo siguiente:

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)); 
    } 
} 
Cuestiones relacionadas