我正在设计一个简单的课程,用于在托管网站上记录消息。
为了存储消息,我创建了这个简单的类结构:
public class StoredMsg {
public StoredMsg() {
}
public string From { get; set; }
public string Date { get; set; }
public string Message { get; set; }
}
将使用StoredMessages : List<StoredMsg>
类编写和回读这些消息。
这是Read
方法的原始格式:
public void Read() {
//string xmlPath = WebPage.Server.MapPath(XML_PATH);
if (File.Exists(xmlPath)) {
using (var xr = new XmlTextReader(xmlPath)) {
StoredMsg item = null;
while (xr.Read()) {
if (xr.NodeType == XmlNodeType.Element) {
if (xr.Name == HEAD) {
if (item != null) {
this.Add(item);
}
item = new StoredMsg();
} else if (xr.Name == FROM) {
item.From = xr.ReadElementString();
} else if (xr.Name == DATE) {
item.Date = xr.ReadElementString();
} else if (xr.Name == MESSAGE) {
item.Message = xr.ReadElementString();
}
}
}
xr.Close();
}
}
}
Write
方法最初采用以下格式:
public void Write(StoredMsg item) {
using (var stream = File.Open(xmlPath, FileMode.Append, FileAccess.Write, FileShare.Read)) {
using (var xw = new System.Xml.XmlTextWriter(stream, Encoding.UTF8)) {
xw.WriteStartElement(HEAD);
{
xw.WriteWhitespace("\r\n\t");
xw.WriteElementString(FROM, item.From);
xw.WriteWhitespace("\r\n\t");
xw.WriteElementString(DATE, item.Date);
xw.WriteWhitespace("\r\n\t");
xw.WriteElementString(MESSAGE, item.Message);
xw.WriteWhitespace("\r\n");
}
xw.WriteEndElement();
xw.WriteWhitespace("\r\n");
}
stream.Close();
}
}
问题是Read
方法不喜欢XML结构中的内容,所以我的列表总是空的。
在托管网站上很难解决这个问题,因此我开始在网上查看示例,看看我可能做错了什么。
在我搜索过程中,我发现Microsoft's How to: Write Object Data to an XML File (C# and Visual Basic)向我展示了简化Write
方法的简化方法:
private XmlSerializer serializer;
public StoredMessages() {
serializer = new XmlSerializer(typeof(StoredMsg));
}
public void Write(StoredMsg item) {
using (var file = new StreamWriter(xmlPath, true)) {
serializer.Serialize(file, item);
}
}
对我而言,简单而优雅!
对此感到高兴,我继续Microsoft's How to: Read Object Data from an XML File (C# and Visual Basic),所以我也可以实现它。
我能做的最好的事情就是写下我的方法:
public void Read() {
if (File.Exists(xmlPath)) {
using (var file = new StreamReader(xmlPath)) {
// How do I handle multiple nodes?
// http://msdn.microsoft.com/en-us/library/vstudio/ms172872.aspx
var item = (StoredMsg)serializer.Deserialize(file);
this.Add(item);
}
}
}
我非常有兴趣看到有人告诉我如何阅读Linq to XML中的所有项目,我会给出+1,但这里的问题是我将如何阅读所有使用此数据的数据{ {1}}以上技术。
我是否错误地将反序列化对象转换为Read
而不是其他内容?如果是这样,其他东西会是什么?
StoredMsg
?StoredMsg[]
?List<object>
?感谢阅读所有这些,我希望我的代码对其他人也清晰可见。
作为屏幕截图提供的示例数据,以防止其他人轻易抓取我的电子邮件地址:
答案 0 :(得分:1)
这是更通用的方法,不,你可以将任何对象传递给读/写
void Write<T>(Stream s,T obj)
{
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(s, obj);
}
T Read<T>(Stream s)
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(s);
}
例如
StoredMsg[] msgs = .....;
Write(stream, msgs);
或
StoredMsg[] msgs = Read<StoredMsg[]>(stream());
修改强>
void Write<T>(string fileName, T obj)
{
using (var stream = File.Create(fileName))
{
Write(stream, obj);
}
}
T Read<T>(string fileName)
{
using (var stream = File.Open(fileName, FileMode.Open))
{
return Read<T>(stream);
}
}
答案 1 :(得分:1)
假设有类似的XML结构:
<Messages>
<MessageHead>
<From>Stackoverflow</From>
<Date>09/05/2013</Date>
<Message>Hello world</Message>
</MessageHead>
<MessageHead>
<From>Stackoverflow</From>
<Date>09/05/2013</Date>
<Message>Second Message</Message>
</MessageHead>
</Messages>
您可以使用LINQ to XML查询将每个MessageHead
子节点作为单个消息读取:
var nodes = (from n in xml.Descendants("MessageHead")
select new
{
From = (string)n.Element("From").Value,
Date = (string)n.Element("Date").Value,
Message = (string)n.Element("Message").Value
}).ToList();
这给出了包含以下两个节点的列表:
从那里可以很容易地将它们映射到你的班级,例如
foreach (var n in nodes)
{
StoredMessage s = new StoredMessage();
s.from = n.From;
s.date = n.Date;
s.message = n.Message;
}