将列表集索引反序列化为对象属性

时间:2015-09-21 05:23:56

标签: c# xml

我有以下XML

<ItemsRoot>
     <ItemList>
         <Item>
             <Name>A</Name>
             <ItemList>
                 <Item>
                    <Name>AA</Name>
                 </Item>
                 <Item>
                    <Name>AB</Name>
                 </Item>
             </ItemList>
         </Item>
         <Item>
             <Name>B</Name>
         </Item>
         <Item>
             <Name>C</Name>
         </Item>
     </ItemList>
</ItemsRoot>

我的课程

public class Item 
{
   [XmlIgnore()]
   public int ItemIndex {get;set;}

   public string Name {get;set;}

   private Item[] itemsList;
   [XmlElement(IsNullable = true)]
   [XmlArrayItem("Item", typeof(Item))]
   [XmlArray("ItemList")]
   public Item[] ItemsList
   {
        get
        {
            return itemsList;
        }
        set
        {
            itemsList= value;
        }
   }

}

[XmlRoot("ItemsRoot")]
public class ItemsRoot
{
     private Item[] itemsList;
     [XmlArrayItem("Item", typeof(Item))]
     [XmlArray("ItemList")]
     public Item[] ItemsList
     {
        get
        {
            return itemsList;
        }
        set
        {
            itemsList= value;
        }
     }
}

反序列化代码:

public static object XmlDeserialize(string dataXML, Type objectType)
{
    XmlDocument xDoc = new XmlDocument();
    xDoc.LoadXml(dataXML);
    XmlNodeReader xNodeReader = new XmlNodeReader(xDoc.DocumentElement);
    XmlSerializer xmlSerializer = new XmlSerializer(objectType);
    var objectData = xmlSerializer.Deserialize(xNodeReader);

    return objectData;
}

所以我试图做的是当我反序列化xml时,我想用列表中对象的索引填充ItemIndex变量。

即。

  

名称为A的项目对象将为索引0
  名称为B的Item对象将为索引1   等等

然后

  

项目AA将再次为索引0   项目AB将是索引1
  等等

我不太关心何时填充ItemIndex。这可能发生在反序列化之后,我只是认为这是一个很好的做法。

4 个答案:

答案 0 :(得分:0)

这应该可以解决问题 -

public class ItemsRoot
{
    public List<Item> ItemList { get; set; }
}

public class Item
{
    public string Name { get; set; }
    public List<Item> ItemList { get; set; }
}

<强>更新

var s = "<ItemsRoot><ItemList><Item><Name>A</Name><ItemList><Item><Name>AA</Name><ItemList><Item><Name>AAA</Name><ItemList><Item><Name>AAAA</Name><ItemList><Item><Name>AAAAA</Name></Item><Item><Name>ABBBB</Name></Item></ItemList></Item><Item><Name>ABBB</Name></Item></ItemList></Item><Item><Name>ABB</Name></Item></ItemList></Item><Item><Name>AB</Name></Item></ItemList></Item><Item><Name>B</Name></Item></ItemList></ItemsRoot>";

var type = new XmlSerializer(typeof(ItemsRoot));

var obj = type.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(s.ToCharArray())));

var reflectedType = ((ItemsRoot)obj).ItemList.Select((item, index) => new Item
        {
            Index = index,
            ItemList = Find(item),
            Name = item.Name
        });

static List<Item> Find(Item item)
{
        return item.ItemList.Select((j, k) => new Item
    {
     Name = j.Name,
     ItemList = Find(j),//j.ItemList,
     Index = k//Find(item.ItemList, j)
    }).ToList();
}

答案 1 :(得分:0)

以下是我将如何做到这一点的伪代码。

这里我从磁盘读取Xml文件。

public static IEnumerable<XElement> StreamXmlDoc(Stream inputStream, string nodeName)
{
    using (var reader = new StreamReader(inputStream))
    {
        using (var xmlReader = XmlReader.Create(reader))
        {
            xmlReader.MoveToContent();

            while (xmlReader.Read())
            {
                switch (xmlReader.NodeType)
                {
                    case XmlNodeType.Element:
                        if (xmlReader.Name == nodeName)
                        {
                            var xElement = XElement.ReadFrom(xmlReader) as XElement;

                            if (xElement != null)
                            {
                                yield return xElement;
                            }
                        }
                        break;
                }

            }
        }
    }
}

然后,当您调用StreamXmlDoc方法时,您可以根据需要填充模型,如下面的示例所示。

var counter = 0;
    var serializedObjects = XmlHelper.StreamXmlDoc(fs, NodeName);

    foreach (var element in serializedObjects)
    {
        // Convert (Deserialize) the patient XElement to an instance of the DESPatientModel class.
        var item = XmlHelper.XmlDeserialize(element.ToString(), typeof(YourType));
        item.ItemIndex = counter++;
    }

答案 2 :(得分:0)

我找到了一种方法来做到这一点。

master班级中我添加了以下内容:

Item

因此,在反序列化后,我有以下内容:

public class Item
{
.
.
.
    //method that will set the ItemIndex to the current index
    public void UpdateIndex(int index)
    {
        this.ItemIndex = index;
        if (this.ItemsList != null)
        {
            this.ItemsList = this.ItemsList.Select((x,index) => x.UpdateIndex(index+1)).ToList();
        }
    }   
}

它可以根据需要完成工作。

答案 3 :(得分:0)

如果仅在反序列化后访问ItemIndex属性,则可以使用:

public class Item 
{
    [XmlIgnore()]
    public int ItemIndex {get;set;}
    ...
    public Item[] ItemsList
    {
       get
       {
          return itemsList;
       }
      set
       {
           itemsList = value;
           if (itemsList != null)
           {
                for(int i = 0; i < itemsList.Length; ++i)
                {
                   itemsList[i].ItemIndex = i;
                }   
           }
       }
   }


 }

在更通用的情况下,考虑将{Parent}属性添加到Item类并动态计算itemIndex。在这种情况下,您还需要定义自己的CollectionType: Collection<Item>类型而不是Item[]