2012-05-07 61 views
3

所以我有以下方法:XML序列化 - 抛自定义错误

private int? myIntField 
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] 
public int? IntField{ 
    get { 
     return this.myIntField; 
    } 
    set { 
     this.myIntField= value; 
    } 
} 

现在,我反序列化从一个帖子XML,如果出于某种原因,我得到一个字符串,如“这里是INT现场:55444" ,而不是55444,我响应得到的错误是:Input string was not in a correct format.这是不是很具体,特别是考虑到我有一个以上的INT场我需要验证。

本来,我打算是这样的:

private string myIntField 
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] 
public int? IntField{ 
    get { 
     return this.myIntField.CheckValue(); 
    } 
    set { 
     this.myIntField= value; 
    } 
} 

如果校验值进行try-parse为Int32,如果失败则返回一个空,并增加了一个错误列表。但是,我似乎无法为生成的类指定这个设置。

有我的方式,如果我在的地方整型,DateTime是否等得到的字符串我可以抛出一个特定的错误?

+1

您应该只对通过序列化创建的数据使用反序列化。在其他情况下,特别是当您必须处理可能的错误时,您应该只是定期解析输入(例如,使用LINQ to XML,XPath等) – eWolf

+0

@Tonnie:您建议的方法看起来像是有效的方法。 “我似乎无法为这些生成的课程设置这个设置”,你的意思是什么。 – Phil

+0

@Tonnie:你也是'post'的意思。一个HTTP POST或博客文章? – Phil

回答

3

“输入字符串的不正确的格式”的消息来自于一个标准System.FormatException通过调用int.Parse引发,添加到执行反序列化的自动生成的程序集中。我不认为你可以添加一些自定义逻辑。

一种解决办法是做这样的事情:

[XmlElement("IntField")] 
    [Browsable(false)] // not displayed in grids 
    [EditorBrowsable(EditorBrowsableState.Never)] // not displayed by intellisense 
    public string IntFieldString 
    { 
     get 
     { 
      return DoSomeConvert(IntField); 
     } 
     set 
     { 
      IntField = DoSomeOtherConvert(value); 
     } 
    } 

    [XmlIgnore] 
    public int? IntField { get; set; } 

它并不完美,因为你仍然可以访问公共IntFieldString,但至少,“真正的” IntField属性只用编程方式,但不是由XmlSerializer(XmlIgnore),而保留值为&的字段对程序员(EditorBrowsable),网格(Browsable)等隐藏,但不是来自XmlSerializer

4

这很容易,如果你对你的XML具有架构(S)和反序列化之前对其进行验证的模式。假设你有你的XML模式(S),你可以初始化XmlSchemaSet中,在其加入您的模式(S)和:

var document = new XmlDocument(); 
document.LoadXml(xml); // this a string holding the XML 
document.Schemas.XmlResolver = null; //if you don't need to resolve every references 
document.Schemas.Add(SchemaSet); // System.Xml.Schema.XmlSchemaSet instance filled with schemas 
document.Validate((sender, args) => { ... }); //args are of type ValidationEventArgs and hold problem if there is one...    

我个人认为这是一个更好的办法,因为你可以验证XML前反序列化并确保XML是正确的,否则解串器将最有可能抛出一个异常,如果事情是错的,你将几乎从来没有能够展现给用户一个有意义的反馈...
PS我建议创建模式(S)描述XML

2

我对你有三种方法。

  • 假设您的数据是由用户在用户界面中输入的,请使用输入验证以确保数据有效。当它应该是一个整数时,允许输入随机字符串似乎很奇怪。

  • 使用完全相同的方法,你上面的提示。下面是使用IXmlSerializable的使用LINQ垫

    void Main() 
    { 
        using(var stream = new StringReader(
           "<Items><Item><IntValue>1</IntValue></Item></Items>")) 
        { 
         var serializer = new XmlSerializer(typeof(Container)); 
    
         var items = (Container)serializer.Deserialize(stream); 
    
         items.Dump(); 
        } 
    } 
    
    [XmlRoot("Items")] 
    public class Container 
    { 
        [XmlElement("Item")] 
        public List<Item> Items { get; set; } 
    } 
    
    public class Item 
    { 
        [XmlElement("IntValue")] 
        public string _IntValue{get;set;} 
    
        [XmlIgnore] 
        public int IntValue 
        { 
         get 
         { 
          // TODO: check and throw appropriate exception 
          return Int32.Parse(_IntValue); 
         } 
        } 
    } 
    
  • 系列化的采取控制一个例子,这里是另一个例子

    void Main() 
    { 
        using(var stream = new StringReader(
           "<Items><Item><IntValue>1</IntValue></Item></Items>")) 
        { 
         var serializer = new XmlSerializer(typeof(Container)); 
    
         var items = (Container)serializer.Deserialize(stream); 
    
         items.Dump(); 
        } 
    } 
    
    [XmlRoot("Items")] 
    public class Container 
    { 
        [XmlElement("Item")] 
        public List<Item> Items { get; set; } 
    } 
    
    public class Item : IXmlSerializable 
    { 
        public int IntValue{get;set;} 
    
        public void WriteXml (XmlWriter writer) 
        { 
         writer.WriteElementString("IntValue", IntValue.ToString()); 
        } 
    
        public void ReadXml (XmlReader reader) 
        { 
         var v = reader.ReadElementString(); 
         // TODO: check and throw appropriate exception 
         IntValue = int.Parse(v); 
        } 
    
        public XmlSchema GetSchema() 
        { 
         return(null); 
        } 
    }