原贴子:http://topic.csdn.net/u/20110213/17/ca32f50f-5f2b-4ca5-aefe-a0f9168b31af.html
需求是在以下的配置中,读取节点:ClassDemoCollection,再把它反序列化成集合类ClassDemoCollection,
最好用Linq to xml实现.
其中ClassDemoCollection是一个可序列化的集合类,详细的可以查看前一贴子.
想不出有什么好的方法处理,拜谢各位.若可以话请试验过后再回贴,
解决了的也请到前一个贴子留名,好贴给分,谢谢!<?xml version="1.0" encoding="utf-8" ?>
<Root>
<A>asdasd</A>
<B value="1">445</B>
<ClassDemoCollection>
<item>
<ItemId>1</ItemId>
<ItemName>test</ItemName>
</item>
<item>
<ItemId>2</ItemId>
<ItemName>test</ItemName>
</item>
</ClassDemoCollection>
</Root>
需求是在以下的配置中,读取节点:ClassDemoCollection,再把它反序列化成集合类ClassDemoCollection,
最好用Linq to xml实现.
其中ClassDemoCollection是一个可序列化的集合类,详细的可以查看前一贴子.
想不出有什么好的方法处理,拜谢各位.若可以话请试验过后再回贴,
解决了的也请到前一个贴子留名,好贴给分,谢谢!<?xml version="1.0" encoding="utf-8" ?>
<Root>
<A>asdasd</A>
<B value="1">445</B>
<ClassDemoCollection>
<item>
<ItemId>1</ItemId>
<ItemName>test</ItemName>
</item>
<item>
<ItemId>2</ItemId>
<ItemName>test</ItemName>
</item>
</ClassDemoCollection>
</Root>
string xml = @"";
XElement xmlPage = XElement.Parse(xml);
var query = xmlPage.Descendants("").Select(x=>x.Element("").Value)
现在是如何在内存里把XElement 对象反序列化为ClassDemoCollection这个类
和xml反序列化为类是一样,但找不知道如何单个反序列化XElement .曾经想过用反射,
但由于ClassDemoCollection包含了多个索引成员,也不行...
1. 把XElement直接能转为xml字符串,再加上xml标准声明,装进 StringReader后使用XmlSerializer直接把字符串反序列化.
2. 装进XDocument加入xml标准声明后反序列化,也不行
3. 反射ClassDemoCollection再读取XElement的节点后逐个赋值,不可行.这样子得到的只是ClassDemoCollection本身的type,而实际要赋值的应该是它的成员属性================================================================>
public class ClassDemoCollection: CollectionBaseCommon<Item>
{
public ConfigItem GetItem(Item model)
{
if (this.List.Count > 0)
{
foreach (Item item in this.List)
{
if (model == item)
return item;
}
}
return null;
}
}ConfigItem是Item的一个派生类,由于整个其他的代码较长,所以没能全贴出来,不好意思.
你可以把上面的类看成[Serializable]
public class ClassDemoCollection: CollectionBaseCommon<Item>
{
}就行了,能从XElement中反序列化ClassDemoCollection就可以了
<Root>
<A>asdasd</A>
<B value="1">445</B>
<ClassDemoCollection>
<Items>
<Item>
<ItemId>1</ItemId>
<ItemName>test</ItemName>
</Item>
<Item>
<ItemId>2</ItemId>
<ItemName>test</ItemName>
</Item>
</Items>
</ClassDemoCollection>
</Root>加Items节点,用来对应List另外有List<T>可用,何必再实现CollectionBaseCommon<T>,
我想你的实现没有MS做的好吧.ClassDemoCollection 做以下修改: [Serializable]
public class ClassDemoCollection
{
public Item GetItem(Item model)
{
if (Items != null && Items.Count > 0)
{
foreach (Item item in Items)
{
if (model == item)
return item;
}
}
return null;
} [XmlArray("Items"),
XmlArrayItem("Item", typeof(Item))]
public List<Item> Items { get; set; }
} 关键的几个xml属性,这是必须要指定的 [XmlArray("Items"),
XmlArrayItem("Item", typeof(Item))] 反序列化操作代码: var doc = new XmlDocument();
doc.Load(@"c:\1.xml");
var node = doc.DocumentElement.SelectSingleNode("ClassDemoCollection");
var reader = new XmlTextReader(node.OuterXml,XmlNodeType.Element,null); var serializer = new XmlSerializer(typeof(ClassDemoCollection));
ClassDemoCollection objToDeserialize = serializer.Deserialize(reader) as ClassDemoCollection;
List<Item> itemList=new List<Item>();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNodeList itemNodes = doc.SelectNodes("/Root/ClassDemoCollection");
foreach (XmlNode itemNode in itemNodes)
{
Item item=new Item();XmlNode itemIdNode= itemNode.SelectSingleNode("ItemId");
item.ItemId=itemIdNode.InnerText;
XmlNode itemNameNode= itemNode.SelectSingleNode("ItemName");
item.ItemName=itemNameNode.InnerText;
itemList.Add(item);
}
则改成 [XmlArray("Items"),
XmlArrayItem("Item", typeof(ConfigItem)),
XmlArrayItem("ConfigItem", typeof(ConfigItem)),]
也就是说,你用来做反序列化的xml输入,
实际是需要根据Item类型来指定相应节点,
如果是Item和ConfigItem混合,则需要是<Items>
<Item>
<ItemId>2</ItemId>
<ItemName>test</ItemName>
</Item>
<ConfigItem>
<ItemId>2</ItemId>
<ItemName>test</ItemName>
</ConfigItem>
</Items>
下面是你的原代码 [Serializable()]
public class CollectionBaseCommon<T> : CollectionBase where T : class
{
/// <summary>
/// 成员索引
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public T this[int index]
{
get
{
return ( this.List[index] ) as T;
}
set
{
this.List[index] = value;
}
} /// <summary>
/// 添加一个成员
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public int Add( T model )
{
return this.List.Add( model );
} /// <summary>
/// 移除一个成员
/// </summary>
/// <param name="model"></param>
public void Remove( T model )
{
this.List.Remove( model );
}
} [Serializable]
public class Item
{
public int ItemId
{
get;
set;
} public string ItemName
{
get;
set;
}
} [Serializable]
public class ClassDemoCollection : CollectionBaseCommon<Item>
{
//此处由 ConfigItem 改成 Item
public Item GetItem( Item model )
{
if ( this.List.Count > 0 )
{
foreach ( Item item in this.List )
{
if ( model == item )
return item;
}
}
return null;
}
}
下面是读取的代码
private static void Test()
{
ClassDemoCollection c = new ClassDemoCollection(); var a = from item in XElement.Load( "d:\\ttt.xml" ).Descendants( "item" )
select new
{
ItemId = int.Parse( item.Element( "ItemId" ).Value ),
ItemName = item.Element( "ItemName" ).Value
}; foreach ( var item in a )
{
c.Add( new Item()
{
ItemId = item.ItemId,
ItemName = item.ItemName
} );
}
}
环境:OS XpSp3
.Net FrameWork4.0
C# 4.0
两位的解决方案都是可行的,,茅塞顿开,一开始我就拘泥地以为只有序列化这种方式可以处理了.
不过对序列化理解也很肤浅,受教了~~~晚上结贴,请也到旧贴留个名好给分,谢谢~