XML serialization and DefaultValue(“”) related problem in c#

前端 未结 4 1630
青春惊慌失措
青春惊慌失措 2021-01-02 06:37

my class property has default value which will be serialize.

public class DeclaredValue
{
    [XmlElement(ElementName = \"Amount\", DataType = \"double\", Is         


        
相关标签:
4条回答
  • 2021-01-02 06:55

    Let me thoroughly describe what is happening.

    When XmlSerializer Deserialize() method is called, it creates a new object using a default constructor. It doesn't apply any DefaultValueAttributes to this object, I beleave, because of assumption that default ctor should "know better" how to initialize values by default. From this point of view - it is logical.

    XmlSerializer doesn't serialize members which values are the same as marked by DefaultValue attribute. From some point of view such behavior is driven by logic too.

    But when you do not initialize members in ctor and call deserialize method, XmlSerializer see no corresponding xml field, but it see that the field/property has DefaultValueAttribute, serializer just leave such value (according to the assumption that the default constructor knows better how to initialize a class "by defaults"). And you've got your zeros.

    Solution To initialize a class members by these DefaultValueAttributes (sometimes it is very handy to have this initialization values just in place) you can use such simple method:

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

    This "public void LoadDefaults()", can be decorated as an Extension to object or use as some static method of a helper class.

    0 讨论(0)
  • 2021-01-02 06:58

    As Henk Holterman mentionned, this attribut doesn't set the default value automatically. Its purpose is mostly to be used by visual designers to reset a property to its default value.

    0 讨论(0)
  • 2021-01-02 07:14

    Per the note on MSDN:

    A DefaultValueAttribute will not cause a member to be automatically initialized with the attribute's value. You must set the initial value in your code.

    Somewhat surprisingly the DefaultValue only regulates the writing of an object, members that are equal to their DefaultValue will not be written out.

    You must still initialize members before or after loading yourself, for example in the constructor.

    0 讨论(0)
  • 2021-01-02 07:15

    As others mentioned, the DefaultValue attribute doesn't initialize the property. You could use a simple loop to set all properties:

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

    Even though ?.Value could return null, it works with non-nullable types, I tested this.

    If only few of your properties have a default value, you should maybe only set the value if it is there.

    If all properties should have a default value, remove the ? to get an error if you forgot one.

    Most likely, arrays won't work, see MajesticRa's solution how to handle that.

    0 讨论(0)
提交回复
热议问题