2010-02-02 51 views
1

我正在使用REST端点编写ASP.NET MVC 2站点。我想通过Rails Web应用程序中的ActiveResource使用此服务。Rails兼容.NET xml序列化

到目前为止,我已经设法在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序列化的根作为<人>,而轨不<人>
  2. 。 NET添加命名空间,而轨道不
  3. .NET序列化属性,如< first_name> rails does < first name>
  4. .NET序列化布尔作为<活性>而导轨确实<活性类型=“布尔”>

数4似乎不会引起任何问题,但其他3原因.NET不反序列化消息。您可以通过使用XmlRoot和XmlElement属性修饰对象来解决这些问题。但这是容易出错和乏味的。

有谁知道一个更好的方式来反序列化.NET中已被序列化的Rails的ActiveResource的XML?

+0

'as rails while'是什么意思?单词的顺序令我困惑。 – smaclell 2010-02-02 16:46:13

+0

对不起,我忘了逃避标签,所以他们没有出现。现在修复。 – 2010-02-02 17:25:27

回答

2

这可以使用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; 
    } 
} 

显然,这需要一个更强大的实施,可能为一个装饰,错误和类型检查。当然,GetOverrides()也可以定制,以提供您想要的特定输出。话虽这么说,这里给出一个样本Person对象的输出结果:给予此输入

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

而且,还进行反序列化正确地提供合适的Person对象。

1

是的。

[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; } 
} 
+0

我在问题中指出这种方法可行,但容易出错且乏味。我正在寻找一种更好的方式,不需要每个物体都要装饰。有任何想法吗?谢谢。 – 2010-02-03 15:43:47

+0

您可以使用一个特殊的XmlSerializer实例化一个XmlAttributeOverrides对象。您必须动态构建XmlAttributeOverrides来处理下划线到破折号的约定以及无用的约定。它将是任何类型对象的单个序列化程序类。 – Cheeso 2010-02-03 21:04:08