2011-05-04 18 views
8

mi propiedad de clase tiene un valor predeterminado que se serializará.Serialización XML y problema relacionado con DefaultValue ("") en C#

public class DeclaredValue 
{ 
    [XmlElement(ElementName = "Amount", DataType = "double", IsNullable = false), DefaultValue(999)] 
    public double Amount { get; set; } 

    [XmlElement(ElementName = "Reference2", DataType = "string", IsNullable = false), DefaultValue("")] 
    public string Reference2 { get; set; } 
} 

por lo que crear una instancia de la clase DeclaredValue y proporcionar un valor para la propiedad Reference2 y no asignan nada por cantidad. así que cuando serializamos la clase DeclaredValue, entonces no encontramos ninguna etiqueta para la cantidad en mi xml. menciono el valor predeterminado para la cantidad "999" y luego, ¿por qué no funciona en la serialización? Quiero que si no se asigna nada para la cantidad, entonces la etiqueta amoun debería estar allí en mi xml con valor predeterminado.

para hacer esto de la manera que necesito para decorar la cantidad de propiedad que siempre viene con el valor predeterminado en xml después de la serialización si el usuario no asigna nada a esta propiedad.

por favor guíame lo que necesito cambiar en el código para obtener el resultado deseado.

Respuesta

15

por la note on MSDN:

Un DefaultValueAttribute se no causa un miembro a ser automáticamente inicializado con el valor del atributo . Debe establecer el valor inicial en su código.

Sorprendentemente, DefaultValue solo regula la escritura de un objeto, los miembros que son iguales a DefaultValue no se escribirán.

Aún debe inicializar los miembros antes o después de cargarse usted mismo, por ejemplo en el constructor.

+0

si establezco el valor explícitamente, entonces lo que hace DefaultValue. su enlace no existe ... así que deme un pequeño código. – Mou

+2

Lo más probable es que necesite un constructor para establecer los valores predeterminados. –

+1

El constructor se invoca antes de que la deserialización llene las propiedades. – Aliostad

1

Como mencionó Henk Holterman, este atributo no establece automáticamente el valor predeterminado. Su objetivo principal es ser utilizado por diseñadores visuales para restablecer una propiedad a su valor predeterminado.

+0

¿Podría mostrarme por código de muestra porque las cosas no están claras? – Mou

+1

¿Qué no está claro? El atributo no tiene efecto. Solo necesita inicializar la propiedad en el constructor. –

7

Permítanme describir a fondo lo que está sucediendo.

Cuando se llama al método XmlSerializer Deserialize(), crea un nuevo objeto utilizando un constructor predeterminado. No aplica ningún DefaultValueAttributes a este objeto, beleave, debido a la suposición de que el ctor predeterminado debería "saber mejor" cómo inicializar los valores de forma predeterminada. Desde este punto de vista, es lógico.

XmlSerializer no serializa los miembros cuyos valores son los mismos marcados por el atributo DefaultValue. Desde cierto punto de vista, dicho comportamiento también es impulsado por la lógica.

Pero cuando no inicializa miembros de Héctor y llama al método deserializar XmlSerializer ver ningún campo XML correspondiente, pero ver que el campo/propiedad tiene DefaultValueAttribute, serializador acaba de salir de dicho valor (de acuerdo con el supuesto de que la el constructor predeterminado sabe mejor cómo inicializar una clase "por defecto"). Y tienes tus ceros.

Solución para inicializar un miembros de la clase de estos DefaultValueAttributes (a veces es muy útil tener estos valores de inicialización justo en su lugar) se puede utilizar como método simple:

public YourConstructor() 
    { 
     LoadDefaults(); 
    } 

    public void LoadDefaults() 
    { 
     //Iterate through properties 
     foreach (var property in GetType().GetProperties()) 
     { 
      //Iterate through attributes of this property 
      foreach (Attribute attr in property.GetCustomAttributes(true)) 
      { 
       //does this property have [DefaultValueAttribute]? 
       if (attr is DefaultValueAttribute) 
       { 
        //So lets try to load default value to the property 
        DefaultValueAttribute dv = (DefaultValueAttribute)attr; 
        try 
        { 
         //Is it an array? 
         if (property.PropertyType.IsArray) 
         { 
          //Use set value for arrays 
          property.SetValue(this, null, (object[])dv.Value); 
         } 
         else 
         { 
          //Use set value for.. not arrays 
          property.SetValue(this, dv.Value, null); 
         } 
        } 
        catch (Exception ex) 
        { 
         //eat it... Or maybe Debug.Writeline(ex); 
        } 
       } 
      } 
     } 
    } 

Este "LoadDefaults public void() ", se puede decorar como una extensión para objetar o usar como un método estático de una clase auxiliar.

0

Como han mencionado otros, el atributo DefaultValue no inicializa la propiedad. Se puede usar un bucle fácil de configurar todas las propiedades:

foreach (var property in GetType().GetProperties()) 
    property.SetValue(this, ((DefaultValueAttribute)Attribute.GetCustomAttribute(
     property, typeof(DefaultValueAttribute)))?.Value, null); 

A pesar de que podría volver ?.Valuenull, funciona con tipos no anulable, he probado esto.

Si solo algunas de sus propiedades tienen un valor predeterminado, quizás solo deba establecer el valor si está allí.

Si todas las propiedades deben tener un valor predeterminado, elimine el ? para obtener un error si olvidó uno.

Lo más probable es que las matrices no funcionen; consulte la solución de MajesticRa sobre cómo manejarlo.

Cuestiones relacionadas