代码之家  ›  专栏  ›  技术社区  ›  Kevin Berridge

与Rails兼容的.NET XML序列化

  •  1
  • Kevin Berridge  · 技术社区  · 15 年前

    我正在编写一个带有rest端点的asp.net mvc 2站点。我想在rails web应用程序中使用activeresource来使用这个服务。

    到目前为止,我已经成功地在asp.net mvc中设置了符合activeresource约定的路由。但是,我遇到的问题是对activeresource发送给rest服务的数据进行反序列化。

    看起来Rails的XML序列化与.NET非常不同(但我在任何地方都找不到这些约定的文档)。例如,对于这样的.NET类:

    public class Person
    {
      public string first_name { get; set; }
      public string last_name { get; set; }
      public bool active { get; set; }
    }
    

    以下是一些不同之处:

    1. .net将根序列化为<person>而rails将根序列化为<person>
    2. .NET添加命名空间,而Rails不
    3. .NET序列化属性,如<名字>而Rails序列化属性<名字>
    4. .net将bool序列化为<active>而rails将bool序列化为<active type=“boolean”>

    数字4似乎不会导致任何问题,但其他3则会导致.NET无法反序列化消息。可以通过使用xmlroot和xmlelement属性装饰对象来解决这些问题。但这很容易出错,也很乏味。

    有没有人知道在.net中反序列化xml的更好方法,它已经被rails的activeresource序列化了?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Tarsier    15 年前

    这可以通过使用 XmlAttributeOverrides

    下面是一个基本的例子, GetOverrides() 作为重要部分:

    public class RailsXmlSerializer
    {
      private Type type;
    
      public RailsXmlSerializer(Type type)
      {
        this.type = type;
      }
    
      public void Serialize(Stream stream, object o)
      {
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");
    
        XmlSerializer xmlSerializer = new XmlSerializer(type, GetOverrides(type));
        xmlSerializer.Serialize(stream, o, ns);
      }
    
      public object Deserialize(Stream stream)
      {
        XmlSerializer xmlSerializer = new XmlSerializer(type, GetOverrides(type));
        return xmlSerializer.Deserialize(stream);
      }
    
      private XmlAttributeOverrides GetOverrides(Type type)
      {
        XmlAttributeOverrides overrides = new XmlAttributeOverrides();
    
        XmlAttributes classAttributes = new XmlAttributes();
        classAttributes.XmlType = new XmlTypeAttribute(type.Name.ToLower());
        overrides.Add(type, classAttributes);
    
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(type))
        {
          XmlAttributes propertyAttributes = new XmlAttributes();
          propertyAttributes.XmlElements.Add(new XmlElementAttribute(property.Name.ToLower().Replace('_', '-')));
          overrides.Add(type, property.Name, propertyAttributes);
        }
    
        return overrides;
      }
    }
    

    显然,这需要一个更健壮的实现,可能作为 XmlSerializer ,并进行错误和类型检查。当然, 获取重写() 也可以定制以提供您想要的特定输出。也就是说,这是给定一个样本的结果输出 Person 对象:

    <?xml version="1.0" encoding="utf-16"?>
    <person>
      <first-name>Jason</first-name>
      <last-name>Bourne</last-name>
      <active>true</active>
    </person>
    

    而且,给定这个输入,反序列化也会正确执行,以提供适当的person对象。

        2
  •  1
  •   Cheeso    15 年前

    对。

    [XmlType("person",   // issue #1
         Namespace="")]  // issue #2
    public class Person 
    { 
      [XmlElement("first-name")]  // issue #3
      public string first_name { get; set; } 
    
      [XmlElement("last-name")]  // issue #3
      public string last_name { get; set; } 
    
      public bool active { get; set; } 
    }