加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#Xml序列化,集合和根元素

发布时间:2020-12-16 05:55:13 所属栏目:百科 来源:网络整理
导读:我的应用程序串行化流中的对象. 以下是我需要的样本: links link href="/users" rel="users" / link href="/features" rel="features" //links 在这种情况下,对象是’links’对象的集合. ———–第一版 起初我使用DataContractSerializer,但是不能将成员序
我的应用程序串行化流中的对象.
以下是我需要的样本:
<links>
  <link href="/users" rel="users" />
  <link href="/features" rel="features" />
</links>

在这种情况下,对象是’links’对象的集合.

———–第一版

起初我使用DataContractSerializer,但是不能将成员序列化为属性(source)

这是对象:

[DataContract(Name="link")]
public class LinkV1
{
    [DataMember(Name="href")]
    public string Url { get; set; }

    [DataMember(Name="rel")]
    public string Relationship { get; set; }
}

结果如下:

<ArrayOflink xmlns:i="...." xmlns="...">
  <link>
    <href>/users</href>
    <rel>users</rel>
  </link>
  <link>
    <href>/features</href>
    <rel>features</rel>
  </link>
</ArrayOflink>

———–第二版

好的,不安静我想要的,所以我尝试了经典的XmlSerializer,但是…哦,哦,你不能指定根元素的名称&的集合元素如果根元素是一个集合…

这是代码:

[XmlRoot("link")]
public class LinkV2
{
    [XmlAttribute("href")]
    public string Url { get; set; }

    [XmlAttribute("rel")]
    public string Relationship { get; set; }
}

结果如下:

<ArrayOfLinkV2>
  <LinkV2 href="/users" rel="users" />
  <LinkV2 href="/features" rel="features" />
  <LinkV2 href="/features/user/{keyUser}" rel="featuresByUser" />
</ArrayOfLinkV2>

———–第三版

使用XmlSerializer一个根元素:

[XmlRoot("trick")]
public class TotallyUselessClass
{
    [XmlArray("links"),XmlArrayItem("link")]
    public List<LinkV2> Links { get; set; }
}

其结果:

<trick>
  <links>
    <link href="/users" rel="users" />
    <link href="/features" rel="features" />
    <link href="/features/user/{keyUser}" rel="featuresByUser" />
  </links>
</trick>

尼斯,但我不想要那个根节点!
我希望我的收藏是根节点.

以下是约束:

>序列化代码是通用的,它可以与任何可序列化的方式一起使用
>反操作(反序列化)也必须工作
>我不想正则表达式(我在输出流中直接序列化)

我现在的解决方案是什么

编码我自己的XmlSerializer
> Trick XmlSerializer当它与一个集合工作(我试过,找到一个XmlRootElement和plurialize它来生成自己的XmlRootAttribute,但是当反序列化项目名称仍然保持类名时会导致问题)

任何想法 ?

在这个问题上真正困扰我的是,我想要的似乎真的很简单

解决方法

好的,这是我的最终解决方案(希望它有助于某人),可以序列化一个纯数组,List<>,HashSet&

要实现这一点,我们需要告诉serializer什么根节点使用,这是一个棘手的…

1)在可序列化的对象上使用’XmlType’

[XmlType("link")]
public class LinkFinalVersion
{
    [XmlAttribute("href")]
    public string Url { get; set; }

    [XmlAttribute("rel")]
    public string Relationship { get; set; }
}

2)编写一个“智能根检测器收集”方法,这将返回一个XmlRootAttribute

private XmlRootAttribute XmlRootForCollection(Type type)
{
    XmlRootAttribute result = null;

    Type typeInner = null;
    if(type.IsGenericType)
    {
        var typeGeneric = type.GetGenericArguments()[0];
        var typeCollection = typeof (ICollection<>).MakeGenericType(typeGeneric);
        if(typeCollection.IsAssignableFrom(type))
            typeInner = typeGeneric;
    }
    else if(typeof (ICollection).IsAssignableFrom(type)
        && type.HasElementType)
    {
        typeInner = type.GetElementType();
    }

    // yeepeeh ! if we are working with a collection
    if(typeInner != null)
    {
        var attributes = typeInner.GetCustomAttributes(typeof (XmlTypeAttribute),true);
        if((attributes != null)
            && (attributes.Length > 0))
        {
            var typeName = (attributes[0] as XmlTypeAttribute).TypeName + 's';
            result = new XmlRootAttribute(typeName);
        }
    }
    return result;
}

3)将该XmlRootAttribute推送到序列化程序中

// hack : get the XmlRootAttribute if the item is a collection
var root = XmlRootForCollection(type);
// create the serializer
var serializer = new XmlSerializer(type,root);

我告诉你这很棘手;)

为了改善这一点,您可以:

A)创建一个XmlTypeInCollectionAttribute来指定自定义根名称(如果基本的复合不符合您的需要)

[XmlType("link")]
[XmlTypeInCollection("links")]
public class LinkFinalVersion
{
}

B)如果可能,缓存您的XmlSerializer(例如在静态字典中).

在我的测试中,建立一个没有XmlRootAttributes的XmlSerializer需要3ms.如果指定一个XmlRootAttribute,它大约需要80ms(只需要一个自定义的根节点名称!)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读