Pregunta

Utilizando .Net 3.0 y VS2005.

Los objetos en cuestión se consumen desde un servicio WCF y luego se serializan de nuevo en XML para una API heredada. Entonces, en lugar de serializar el TestObject, estaba serializando .TestObject al que le faltaba el atributo [XmlRoot]; sin embargo, todos los atributos [Xml *] para los elementos secundarios estaban en el código proxy generado, por lo que funcionaron bien. Así que todos los elementos secundarios funcionaron bien, pero el elemento de encierro no funcionó porque el atributo [XmlRoot] no se incluyó en el código proxy generado. El objeto original que incluía el atributo [XmlRoot] se serializa bien manualmente.

¿Puedo hacer que el código proxy incluya el atributo [XmlRoot] para que la clase proxy generada también se serialice correctamente? Si no puedo hacer eso, sospecho que tendré que usar [XmlType] pero eso causa un pequeño caos que me obliga a cambiar otros componentes, por lo que preferiría el primero. También quiero evitar tener que editar manualmente la clase de proxy autogenerado.

Aquí hay un código de ejemplo (he incluido el cliente y el servicio en la misma aplicación porque es rápido y para propósitos de prueba. Comente el código de referencia del servicio y agregue la referencia del servicio mientras ejecuta la aplicación, luego elimine el comentario del servicio codificar y ejecutar.)

namespace SerializationTest {  
  class Program {  
    static void Main( string[] args ) {  

        Type serviceType = typeof( TestService );  
        using (ServiceHost host = new ServiceHost(   
            serviceType,   
            new Uri[] {   
                new Uri( "http://localhost:8080/" )  
            }  

        ))
        {

            ServiceMetadataBehavior behaviour = new ServiceMetadataBehavior();  
            behaviour.HttpGetEnabled = true;  
            host.Description.Behaviors.Add( behaviour );  

            host.AddServiceEndpoint( serviceType, new BasicHttpBinding(), "TestService" );  
            host.AddServiceEndpoint( typeof( IMetadataExchange ), new BasicHttpBinding(), "MEX" );  


            host.Open();  

            TestServiceClient client = new TestServiceClient();  
            localhost.TestObject to = client.GetObject();  

            String XmlizedString = null;  
            using (MemoryStream memoryStream = new MemoryStream()) {
                XmlSerializer xs = new XmlSerializer( typeof( localhost.TestObject ) );  
                using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream)) {
                    xs.Serialize( xmlWriter, to );  
                    memoryStream = (MemoryStream)xmlWriter.BaseStream;  
                    XmlizedString = Encoding.UTF8.GetString( memoryStream.ToArray() );  
                    Console.WriteLine( XmlizedString );  
                }    
            }    
        }

        Console.ReadKey();  
    }  
}  

[Serializable]  
[XmlRoot( "SomethingElse" )]  
public class TestObject {  

    private bool _worked;  

    public TestObject() { Worked = true; }  

    [XmlAttribute( AttributeName = "AttributeWorked" )]  
    public bool Worked {  
        get { return _worked; }  
        set { _worked = value; }  
    }  
}  

[ServiceContract]  
public class TestService {  

    [OperationContract]  
    [XmlSerializerFormat]  
    public TestObject GetObject() {  
        return new TestObject();  
    }  
  }  
}  

Aquí está el Xml que esto genera.

<?xml version="1.0" encoding="utf-8"?>
<TestObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" AttributeWorked="true" /> 
¿Fue útil?

Solución

Encontré a alguien que proporciona un medio para resolver esta situación:

Weblog de Matevz Gacnik

Usando ese enfoque de XmlAttributeOverrides , escribí lo siguiente:

    private static XmlSerializer GetOverridedSerializer()
    {
        // set overrides for TestObject element
        XmlAttributes attrsTestObject = new XmlAttributes();
        XmlRootAttribute rootTestObject = new XmlRootAttribute("SomethingElse");
        attrsTestObject.XmlRoot = rootTestObject;

       // create overrider
       XmlAttributeOverrides xOver = new XmlAttributeOverrides();
       xOver.Add(typeof(localhost.TestObject), attrsTestObject);

       XmlSerializer xSer = new XmlSerializer(typeof(localhost.TestObject), xOver);
       return xSer;
    }

Simplemente coloque ese método en la clase Programa de su ejemplo y reemplace la siguiente línea en Main () :

        //XmlSerializer xs = new XmlSerializer(typeof(localhost.TestObject));
        XmlSerializer xs = GetOverridedSerializer();

Y luego ejecute para ver los resultados.

Aquí está lo que tengo:

<?xml version="1.0" encoding="utf-8"?><SomethingElse xmlns:xsi="http://www.w3.o
rg/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Attribu
teWorked="true" />

Otros consejos

== IF ==

Esto es solo para el atributo XmlRoot . El XmlSerializer tiene un constructor donde puede especificar el atributo XmlRoot .

Felicitaciones a csgero por señalarlo. Su comentario debería ser la solución.

XmlSerializer Constructor (Type, XmlRootAttribute)
  

Inicializa una nueva instancia de la   Clase XmlSerializer que puede serializar   Objetos del tipo especificado en XML.   documentos, y deserializar un XML   documento en objeto de la especificada   tipo. También especifica la clase a   utilizar como elemento raíz XML.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top