C#XML反序列化W /默认值
我有一个对象正在通过C#,.NET 3.5中的XmlSerializer进行序列化/反序列化。其中一个属性(以及更多未来)是一个集合:列表,其中T是一个枚举值。这个序列化/反序列化罚款。C#XML反序列化W /默认值
如果序列化版本没有设置任何值,我们还使用“默认值”机制为对象提供默认值。作为一个简单的例子,这里是我们的冬:
public enum MyEnum {
Value1,
Value2
}
public class Foo
{
public List SomeSetting{ get; set; }
public Foo()
{
SomeSetting = new List();
SomeSetting.Add(MyEnum.Value1);
SomeSetting.Add(MyEnum.Value2);
}
}
此代码工作正常的对象被创建时设置SomeSetting的默认值。
但是,当我们对具有SomeSetting值的xml文件进行反序列化时,此默认值设置会导致问题:xml反序列化程序不会“重置”SomeSetting集合 - 它不会将其清除并填充新数据。相反,它增加了已经存在的数据。所以,如果xml文件将Value1序列化到它中,当我反序列化该文件时,我最终将SomeSettings的{Value1,Value2,Value1}存储为值。
我需要一种方法来进行xml反序列化处理,以便在xml文档中没有用于SomeSetting的数据时存在我的默认值,并且还可以在xml文档中有数据时批量替换SomeSetting值。我怎样才能做到这一点?
仅供参考 - 这不是文档中的唯一属性。该文件确实存在,并且正在为其他“简单”值进行序列化/反序列化。不过,这是造成问题的财产。我必须支持这种情况,因为现在我需要做很多事情。
仅供参考 - 我用IXMLSerializable接口解决了这个问题。请注意,这个代码对于我在这个类中的需求非常具体,所以YMMV。
public void WriteXml(XmlWriter writer)
{
foreach (PropertyInfo prop in GetType().GetProperties())
{
XmlIgnoreAttribute attr;
if (prop.TryGetAttribute(out attr))
continue;
if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(List)))
{
XmlSerializer serializer = new XmlSerializer(prop.PropertyType, new XmlRootAttribute(prop.Name));
serializer.Serialize(writer, prop.GetValue(this, null));
}
else
{
writer.WriteElementString(prop.Name, prop.GetValue(this, null).ToString());
}
}
}
public void ReadXml(XmlReader reader)
{
if (reader.IsEmptyElement)
return;
XmlDocument xDoc = new XmlDocument();
xDoc.Load(reader);
Type type = GetType();
foreach (XmlNode node in xDoc.DocumentElement.ChildNodes)
{
PropertyInfo prop = type.GetProperty(node.Name);
if (prop != null && prop.CanWrite)
{
object value;
if (prop.PropertyType.IsEnum)
{
string stringValue = node.InnerText;
value = Enum.Parse(prop.PropertyType, stringValue);
}
else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(List)))
{
Type enumType = prop.PropertyType.GetGenericArguments()[0];
value = Activator.CreateInstance(prop.PropertyType);
var addMethod = value.GetType().GetMethod("Add");
foreach (XmlNode subNode in node.ChildNodes)
{
object enumValue = Enum.Parse(enumType, subNode.InnerText);
addMethod.Invoke(value, new[] { enumValue });
}
}
else
{
string stringValue = node.InnerText;
value = Convert.ChangeType(stringValue, prop.PropertyType);
}
prop.SetValue(this, value, null);
}
}
}
public XmlSchema GetSchema()
{
return null;
}
快速和肮脏的是执行ISupportInitialize。所有的.NET串行器(IIRC)都尊重这个接口,并在反序列化之后调用EndInit
。
您可以在此处检查集合的内容,并确定是否应该在当时添加默认值。我还建议检查一下,看看你的实例在第一次使用之前是否已经初始化,如果没有,就抛出异常。这将确保你的类的其他用户知道你的实例在使用之前必须被初始化。
似乎并没有工作...方法从该接口不被xml序列化程序调用。 – 2009-12-28 15:30:53
我觉得IXmlSerializable接口会得到我我想要的......任何人有如何使用解决我的问题,这个接口有何建议? – 2009-12-28 17:05:06
另一种选择可能是,而不是分析自己 http://*.com/questions/14768052/c-sharp-xml-deserialize-plus-design-suggestions – surya 2013-02-08 19:31:18