通用属性的序列化

时间:2011-02-11 19:18:56

标签: c# .net xml generics xml-serialization

有人可以向我解释为什么第一个例子将序列化为XML,第二个例子会抛出有关尝试将所有类型转换为彼此的运行时错误吗?如果我从第二个示例中删除XmlElement属性,它将序列化,但XML元素名称将是错误的("项目"而不是为其类型指定的那个)。第一个片段是使用模式文件从XSD工具生成的。

更好的是,有没有办法让这个工作?我更喜欢使用向对象/从对象进行强制转换的泛型类型。它使代码更清晰。明确地投射对象表明您的设计存在问题。

public partial class OAIPMHtype
{
    private object itemsField;

    [XmlElement( "GetRecord", typeof( GetRecordType ) )]
    [XmlElement( "Identify", typeof( IdentifyType ) )]
    [XmlElement( "ListIdentifiers", typeof( ListIdentifiersType ) )]
    [XmlElement( "ListMetadataFormats", typeof( ListMetadataFormatsType ) )]
    [XmlElement( "ListRecords", typeof( ListRecordsType ) )]
    [XmlElement( "ListSets", typeof( ListSetsType ) )]
    [XmlElement( "error", typeof( OAIPMHerrorType ) )]
    public object Item
    {
        get { return this.itemsField; }
        set { this.itemsField = value; }
    }
}

这不会序列化。

public class OaiPmh<T>
{
    private T itemsField;

    [XmlElement( "GetRecord", typeof( GetRecordType ) )]
    [XmlElement( "Identify", typeof( IdentifyType ) )]
    [XmlElement( "ListIdentifiers", typeof( ListIdentifiersType ) )]
    [XmlElement( "ListMetadataFormats", typeof( ListMetadataFormatsType ) )]
    [XmlElement( "ListRecords", typeof( ListRecordsType ) )]
    [XmlElement( "ListSets", typeof( ListSetsType ) )]
    [XmlElement( "error", typeof( OAIPMHerrorType ) )]
    public T Item
    {
        get { return itemsField; }
        set { itemsField = value; }
    }
}

为了进一步澄清,我在创建XmlSerializer对象时尝试指定所有额外类型,但这没有帮助。

这是抛出的例外:

Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'ErrorRequest' to 'GetRecordRequest'
error CS0030: Cannot convert type 'ErrorRequest' to 'ListRecordsRequest'
error CS0030: Cannot convert type 'ErrorRequest' to 'IdentityRequest'
error CS0030: Cannot convert type 'ErrorRequest' to 'ListSetsRequest'
error CS0030: Cannot convert type 'ErrorRequest' to 'ListIdentifiersRequest'
error CS0030: Cannot convert type 'ErrorRequest' to 'ListMetadataFormatsRequest'
error CS0029: Cannot implicitly convert type 'ListSetsRequest' to 'ErrorRequest'
error CS0029: Cannot implicitly convert type 'ListIdentifiersRequest' to 'ErrorRequest'
error CS0029: Cannot implicitly convert type 'ListMetadataFormatsRequest' to 'ErrorRequest'
error CS0029: Cannot implicitly convert type 'GetRecordRequest' to 'ErrorRequest'
error CS0029: Cannot implicitly convert type 'ListRecordsRequest' to 'ErrorRequest'
error CS0029: Cannot implicitly convert type 'IdentityRequest' to 'ErrorRequest

&#39;

使用泛型类型是有意义的,看看类型在编译时是如何特定绑定的。但是看看它如何与对象引用一起工作,在我看来它也应该使用泛型类型。

3 个答案:

答案 0 :(得分:2)

您是否查看过“如何序列化通用类型”问题下的Generics FAQ页面?它可能会帮助你。

答案 1 :(得分:2)

我认为CS0029 compiler error page on MSDN提供了您正在寻找的信息。

根据我阅读本文的方式,您的第一个示例有效,因为您的课程中没有发生转换。因为你明确地传递Object,所以不需要进行转换,也不会抛出编译器错误。

在第二个示例中,直到运行时才知道类型。通过指定多个XmlElement属性,编译器认为所有这些类型都必须是可互换的。但是,由于您没有为这些提供显式转换,编译器担心这两种类型之间的转换可能会缩小转换并引发错误。

答案 2 :(得分:0)

为不同类型设置不同序列化元素的唯一方法是使用objectIXmlSerializable

不幸的是,XmlSerializer无法访问非公共属性。因此,通过第二个公共属性将项目公开为object可以进行序列化。但我不会在实际情况下使用它:

[XmlElement("GetRecord", typeof(GetRecordType))]
[XmlElement("Identify", typeof(IdentifyType))]
public object ItemSerializer
{
    get { return this.Item; }
    set { this.Item = (T)value; }
}

[XmlIgnore]
public T Item
//...