C#xml序列化必填字段
我需要将一些字段标记为需要在XML文件中写入的字段,但没有成功。我有一个大约30个属性的配置类,这就是为什么我不能像这样封装所有属性C#xml序列化必填字段,c#,.net,xml,serialization,xml-serialization,C#,.net,Xml,Serialization,Xml Serialization,我需要将一些字段标记为需要在XML文件中写入的字段,但没有成功。我有一个大约30个属性的配置类,这就是为什么我不能像这样封装所有属性 public string SomeProp { get { return _someProp; } set { if (_someProp == null) throw new ArgumentNullException("value");
public string SomeProp
{
get { return _someProp; }
set
{
if (_someProp == null)
throw new ArgumentNullException("value");
_someProp = value;
}
}
null是代码中的有效值,但不是XML中的有效值。我试图使用xmltattribute
,但它并没有像我预期的那样产生影响(反序列化时出现IOException)
例如,此代码:
[XmlElement(IsNullable = true)]
public String Name { get; set; }
[XmlElement(IsNullable = true)]
public String Description { get; set; }
当缺少Name
和Description
标记时,此选项非常有效
澄清: 类别:
public class MyClass
{
[XmlElement(IsNullable = true)]
public String Name { get; set; }
[XmlElement(IsNullable = true)]
public String Description { get; set; }
}
XML:
结果:反序列化成功,说明为空
应为:
异常,未找到描述标记。
我相信您可以遵循两种方法。一个是使用使用模式的验证XmlReader,另一个是反序列化后的反射检查。最后一个选项是我在这里提供的解决方案:
此助手获取一个流,并将给定泛型类型的流反序列化为该类型的实例。一旦该对象存在,就可以迭代并检查其属性是否使用XmlElementAttribute修饰。如果找到该属性,则会检查其IsNullable属性,如果为false且对象实例上的属性为false,则会引发异常
public T ValidatingDeserializer<T>(Stream s)
{
T deserialize = (T)new XmlSerializer( typeof(T)).Deserialize(s);
foreach(var pi in typeof(T).GetProperties())
{
var xmlnull = pi.GetCustomAttribute(typeof(XmlElementAttribute));
if (xmlnull!=null)
{ var xmlnullInst = (XmlElementAttribute) xmlnull;
if (!xmlnullInst.IsNullable && pi.GetValue(deserialize)==null)
{
throw new Exception(String.Format("{0} is null", pi.Name));
}
}
}
return deserialize;
}
ValidateEvent目标
已使用问题中显示的xml的示例架构
您必须使用
XmlSerializer
DataContractSerializer
提供以下选项:
[DataMember(IsRequired = true)]
当遇到空值时,您能否澄清何时要抛出。在序列化或反序列化过程中?这很好,但它应该以递归方式工作。因此,应检查所有字段的所有属性和属性等。这就是为什么我希望实现序列化的标准化。因为我可以手动检查所有内容,但这会花费我很多钱,而且这些类的属性也会被修饰?当然。我知道我们可以检查所有道具,但这么多的反射对我来说太糟糕了。为什么?这是时间/资源关键路径吗?我只是不喜欢反思。但是现在你的答案是最好的。所以我做了标记,tnx。不幸的是,您不能用数据协定序列化程序将属性修饰为属性,所以我不能使用它。必须保留XMLSerializer,但仍然存在问题。
public T ValidatingDeserializer<T>(Stream s)
{
T deserialize = (T)new XmlSerializer( typeof(T)).Deserialize(s);
foreach(var pi in typeof(T).GetProperties())
{
var xmlnull = pi.GetCustomAttribute(typeof(XmlElementAttribute));
if (xmlnull!=null)
{ var xmlnullInst = (XmlElementAttribute) xmlnull;
if (!xmlnullInst.IsNullable && pi.GetValue(deserialize)==null)
{
throw new Exception(String.Format("{0} is null", pi.Name));
}
}
}
return deserialize;
}
MyClass deserialize = ValidatingDeserializer<MyClass>(
new FileStream("result.xml", FileMode.Open));
Console.WriteLine(deserialize.Name);
Console.WriteLine(deserialize.Description);
public XmlReader ReaderFactory(Stream xml, Stream schema)
{
XmlSchemaSet sc = new XmlSchemaSet();
// Add the schema to the collection.
sc.Add(null, XmlReader.Create(schema));
// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.Schemas = sc;
settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);
return XmlReader.Create(xml, settings);
}
private static void ValidationCallBack(object sender, ValidationEventArgs e) {
Console.WriteLine(
"Validation Error: {0} near line: {1}, pos: {2}",
e.Message,
e.Exception.LineNumber,
e.Exception.LinePosition);
throw new Exception("illegal xml content");
}
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns=""
elementFormDefault="qualified">
<xsd:element name="MyClass" >
<xsd:complexType>
<xsd:sequence maxOccurs="1">
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="Description" type="xsd:string" minOccurs="1">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
[DataMember(IsRequired = true)]