2012-05-04 37 views
11

He encontrado un comportamiento sorprendente al usar XmlSerializer en C#. Considera la siguiente pieza de código..NET XmlSerializer y clases anidadas en C#

public class A : IEnumerable 
{ 
    public class B 
    { 
     [XmlAttribute] 
     public string PropA { get; set; } 
     [XmlElement] 
     public string PropB { get; set; } 
    } 

    public IEnumerator GetEnumerator() 
    { 
     yield break; 
    } 
} 

class Program 
{ 
    static void Main (string[] args) 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(A.B)); 

     XmlTextWriter writer = new XmlTextWriter(@"E:\temp\test.xml", Encoding.Default); 
     serializer.Serialize(writer, new A.B() { PropA = "one", PropB = "two" }); 
    } 
} 

En este ejemplo I intenta serializar una instancia de A.B clase anidada, que en sí no hace uso de la clase de contenedor A de ninguna manera. Pero cuando intento para construir el XmlSerializer para ello, la excepción siguiente:

InvalidOperationException fue controlada:

Para ser XML serializable, tipos, que heredan de IEnumerable debe tener una implementación de Agregar (Sistema .Object) en todos los niveles de su jerarquía de herencia . Test.A no implementa Add (System.Object).

XmlSerializer está tratando de aplicar restricciones de serialización contra el tipo A cuando estoy tratando de serializar el tipo A.B. Sin embargo, tengo entendido que, aparte del acceso privilegiado a los datos en instancias del tipo externo, un tipo anidado no es especial y se comporta como si estuviera en un espacio de nombres.

¿Es este conocimiento incorrecto, y hace la semántica de tipos anidados o XmlSerializer justifica este comportamiento, o se siente como un error en XmlSerializer?

En lo que respecta específicamente a la semántica de XmlSerializer, ¿existe algún requisito documentado que imponga restricciones de XmlSerializer en todos los tipos externos cuando se aplica a un tipo anidado?

+1

No tiene problemas con los tipos anidados. Su clase A no tiene una propiedad de tipo 'B'. –

+0

Además, no use 'new XmlTextWriter()'. Eso ha estado en desuso desde .NET 2.0. Use 'XmlWriter.Create()' en su lugar. –

+3

Lo siento, pero ha perdido el sentido de mi pregunta por completo. No estoy tratando de serializar A, y no estoy tratando de serializar B como una propiedad de A. Estoy tratando de serializarlo completamente independiente de A. Y soy consciente de la obsolescencia de TextWriter. Este es un ejemplo artificial de la parte superior de mi cabeza que he tratado de mantener breve. –

Respuesta

0

es el IEnumerable que plantea las restricciones aquí. Si agrega el método Agregar según lo sugerido por la excepción, su código funcionará bien. De nuevo, esto tiene poco que ver con XmlSerialization y más con la forma en que funciona IEnumerable. Por favor corrígeme si estoy fuera de aquí. Compruebe this para una buena discusión sobre el mismo.

+0

Una vez más, sé cuál es la restricción y cómo resolverla. La verdadera pregunta es, ¿por qué esta restricción se aplica a un tipo que no estoy tratando de serializar en realidad? La otra restricción que he observado que es un problema es el constructor predeterminado, aunque tuve más dificultades para aislarlo por ejemplo. –

+0

Justin es correcto. Este es un error en el Serializador XML. Este no es el mismo problema que la pregunta que vinculó. –

0

El XmlSerializer brinda un tratamiento especial a las clases que implementan IEnumerable o ICollection.

detalles más aquí: XmlSerializer and IEnumerable: Serialization possible w/o parameterless constructor: Bug?

+0

El objetivo del ejemplo que proporcioné es que la clase que implementa IEnumerable no es realmente la clase que se serializa. La clase anidada se está serializando y es completamente independiente. El autor de la respuesta aceptada de la pregunta que ha vinculado también parece estar de acuerdo en que se trata de un error. –

1

http://msdn.microsoft.com/en-us/library/vstudio/ms229027%28v=vs.100%29.aspx

Debido a que un tipo anidado es tratado como un miembro del tipo de declarar, el tipo anidado tiene acceso a todos los demás miembros de la clase que se declara.

Entonces, si el serializador desea trabajar con A.B, también necesita la definición de A. Cuando las patadas de validación en IEnumerable.

No importa que B en realidad no se refiere a nada en A :)

0

Probablemente este es un problema muy difícil en la serialización en tiempo de ejecución, pero no lo hago tener alguna buena explicación para este comportamiento. Siento que la restricción de IEnumerable no se aplica a la clase B.

Cuestiones relacionadas