如何让XmlSerializer一直使用序列化属性?我正在使用DefaultValue属性来获得正确的PropertyGrid行为(它以粗体显示与默认值不同的值)。现在,如果我想使用XmlSerializer序列化显示的对象,则xml文件中将没有具有默认值的属性的条目。告诉XmlSerializer序列化它们的最简单方法是什么?我需要它支持“版本”,所以当我稍后在代码中更改默认值时-序列化属性获取它已序列化的值,而不是“最新”值。我可以想到以下几点:但是我有可能遗漏了一些秘密财产,这些财产可以在没有太多痛苦的情况下做到这一点=D。这是我想要的示例:privatebool_allowNegative=false;/////获取或设置是否允许负结果///[Category(CategoryAnalyse)][Admin][TypeConverter(typeof(ConverterBoolOnOff))]//[DefaultValue(false)]*1publicboolAllowNegative{get{返回_allowNegative;}设置{_allowNegative=值;ConfigBase.OnConfigChanged();}}//publicvoidResetAllowNegative(){_allowNegative=false;}*2//publicboolShouldSerializeAllowNegative(){return_allowNegative;}*3//publicboolShouldSerializeAllowNegative(){返回真;}*4如果我取消注释(*1),那么我在PropertyGrid中得到了预期的效果——具有默认值的属性以普通文本显示,否则文本为粗体。然而,XmlSerializer并没有将具有默认值的属性放入xml文件中,这很糟糕(我正在尝试修复它)。如果我取消注释(*2)和(*3),那么它与取消注释(*1)完全一样。如果我取消注释(*2)和(*4),那么XmlSerializer将始终将属性放在xml文件中,但那是因为它们不再具有默认值并且PropertyGrid以粗体文本显示所有值。只要您不需要Xml中的属性,如果您使用DataContractSerializer,您将获得所需的行为。[DataContract]publicclassTest{[DataMember][DefaultValue(false)]publicboolAllowNegative{get;放;}}voidMain(){varsb2=newStringBuilder();vardcs=newDataContractSerializer(typeof(Test));使用(varwriter=XmlWriter.Create(sb2)){dcs.WriteObject(writer,newTest());}Console.WriteLine(sb2.ToString());}产生(减去命名空间等)false您可以使用两个属性://仅用于属性网格:[Category(CategoryAnalyse)][TypeConverter(typeof(ConverterBoolOnOff))][DefaultValue(false)][XmlIgnore]publicboolAllowNegative{得到{返回_allowNegative;}设置{_allowNegative=值;ConfigBase.OnConfigChanged();}}//对于序列化:[Browsable(false)][EditorBrowsable(EditorBrowsableState.Never)][TypeConverter(typeof(ConverterBoolOnOff))][XmlElement("AllowNegative")]publicboolAllowNegative_XML{get{return_allowNegative;}设置{_allowNegative=值;ConfigBase.OnConfigChanged();我相信你正在寻找的是ShouldSerialize()和Reset()。使用它们可以稍微扩展您的类(每个属性两个函数),但是,它确实可以满足您的需求。这是一个简单的例子://你的属性变量privateconstStringMyPropertyDefault="MyValue";私有字符串_MyProperty=MyPropertyDefault;//你的财产//[DefaultValueAttribute("MyValue")]-不能使用DefaultValueANDShouldSerialize()/Reset()publicStringMyProperty{get{return_MyProperty;}设置{_MyProperty=值;}}//重要的!//注意函数名称是“ShouldSerialize...”,后跟//与您的属性完全相同的(!)名称publicBooleanShouldSerializeMyProperty(){//在这里您通常会进行自己的比较并返回true/false//基于属性是否应该被序列化,但是,//在您的情况下,您希望在序列化时始终返回true!//重要的条件语句!如果(!设计模式)返回真;//总是在设计模式之外返回true(仅用于序列化)否则return_MyProperty!=MyPropertyDefault;//在设计模式下,我们实际上与默认值进行比较t值}publicvoidResetMyProperty(){_MyProperty=MyPropertyDefault;请注意,由于您想保留PropertyGrid功能,因此在ShouldSerialize()函数中您必须知道您是否正在序列化我建议您实现某种控制标志,因此始终返回true。请注意,您不能将DefaultValue属性与ShouldSerialize()和Reset()函数一起使用(您只能使用or)。编辑:添加了ShouldSerialize()函数的描述。因为目前无法序列化默认值并让PropertyGrid知道一个属性有它的默认值,所以你必须实现一个条件来检查你是否处于设计模式。假设您的类派生自Component或Control,您将拥有一个仅由VisualStudio在设计时设置的DesignMode属性。条件如下:if(!DesignMode)returntrue;//总是在设计模式之外返回true(仅用于序列化)否则return_MyProperty!=MyPropertyDefault;//在设计模式期间,我们实际上与默认值进行比较编辑2:我们不是在谈论VisualStudio的设计模式。考虑上面的代码,创建另一个名为IsSerializing的属性。在调用XmlSerializer.Serialize之前将IsSerializing属性设置为true,然后再取消设置。最后,将if(!DesignMode)条件语句更改为if(IsSerializing)。可以使用XmlAttributeOverrides覆盖XmlSerializer此行因为我从这里借用了这个想法:staticpublicXmlAttributeOverridesGetDefaultValuesOverrides(Typetype){PropertyDescriptorCollectionc=TypeDescriptor.GetProperties(类型);foreach(PropertyDescriptorpinc){AttributeCollection属性=p.Attributes;DefaultValueAttributedefaultValue=(DefaultValueAttribute)attributes[typeof(DefaultValueAttribute)];XmlIgnoreAttributenoXML=(XmlIgnoreAttribute)attributes[typeof(XmlIgnoreAttribute)];XmlAttributeAttribute属性=(XmlAttributeAttribute)属性[typeof(XmlAttributeAttribute)];if(defaultValue!=null&&noXML==null){XmlAttributeAttributexmlAttribute=newXmlAttributeAttribute(attribute.AttributeName);XmlAttributesxmlAttributes=newXmlAttributes();xmlAttributes.XmlAttribute=xmlAttribute;explicitOverrides.Add(userType,attribute.AttributeName,xmlAttributes);}}返回explicitOverrides;}并使自己成为一个属性来装饰应该发出默认值的类如果你想对所有类都这样做,我相信你可以适应整个概念。公共类EmitDefaultValuesAttribute继承属性PrivateSharedmCacheAsNewDictionary(OfAssembly,XmlAttributeOverrides)PublicSharedFunctionGetOverrides(assemblyAsAssembly)AsXmlAttributeOverridesIfmCache.ContainsKey(assembly)ThenReturnmCache(assembly)assembly.GetTypes()Ift.GetCustomAttributes(GetType(EmitDefaultValuesAttribute),True).Count>0ThenAddOverride(t,xmlOverrides)EndIfNextmCache.Add(assembly,xmlOverrides)返回xmlOverridesEndFunctionPrivateSharedSubAddOverride(tAsType,xmlOverridesAsXmlAttributeOverrides)ForEachpropInt.GetProperties()DimdefaultAttr=prop.GetCustomAttributes(GetType(DefaultValueAttribute),True).FirstOrDefault()DimxmlAttrAsXmlAttributeAttribute=prop.GetCustomAttributes(GetType(XmlAttributeAttribute),True).FirstOrDefault()IfdefaultAttrIsNotNothing并且xmlAttrIsNotNothingThenDimattrsAsNewXmlAttributes'={NewXmlAttributeAttribute}attrs.XmlAttribute=xmlAttr''overide.Add(t,xmlAttr.AttributeName,attrs)xmlOverrides.Add(t,prop.Name,attrs)EndIfNextEndSub因为xsd.exe生成部分类,所以可以在单独的文件中添加这个EmitDefaultValuesAttribute:PublicMyClassPublicPropertySubClass()AsMySubClassEndClassPublicMySubClassEndClass用法如下:以上是C#学习教程:HowtotellXmlSerializertoalwaysuse序列化属性?分享的所有内容,如果对你有用,需要了解更多C#学习教程,希望大家多加关注—DimserializerAsNewXmlSerializer(GetType(MyClass),EmitDefaultValuesAttribute.GetOverrides(GetType(MyClass).大会))本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如有转载请注明出处:
