2010-07-16 80 views
7

问题:我使用可序列化的字典类,在 http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx 处找到,以序列化字典。 这工作正常,但我遇到了一个恼人的问题。可串行化字典,如何设置键名?

 <System.Xml.Serialization.XmlRoot("DataBase")> _ 
    Public Class cDataBase 
     <System.Xml.Serialization.XmlNamespaceDeclarations()> _ 
     Public ns As New System.Xml.Serialization.XmlSerializerNamespaces() 


     <System.Xml.Serialization.XmlElement("Tables")> _ 
     Public Tables1 As New SerializableDictionary(Of String, cTable) 


    End Class ' cDataBase 

当我序列化上面的类的实例,因为这, 创建的XML看起来是这样的:

<Tables> 
<item> 
    <key> 
    <string>MyTable</string> 
    </key> 
    <value> 
    <Table CreationDate="0001-01-01T00:00:00" LastModified="0001-01-01T00:00:00"> 
     <Columns> 
     <Column Name="PrimaryKeyName"> 
      <DataType>Uniqueidentifier</DataType> 
      <Length>36</Length> 
     </Column> 
     </Columns> 
     <Rows> 
     <Row> 
      <Item>Reihe1</Item> 
      <Item>Reihe2</Item> 
      <Item>Reihe3</Item> 
     </Row> 
     <Row> 
      <Item>Reihe1</Item> 
      <Item>Reihe2</Item> 
      <Item>Reihe3</Item> 
     </Row> 

这将是很好的,如果我能想出如何重新命名的关键 <串>到在属性定义

<key> 
    <string>MyTable</string> 
    </key> 

基本上类似的东西XmlArrayItem属性,如下面,如果头(只)的字典是一个数组...

 <System.Xml.Serialization.XmlArray("Tables")> _ 
     <System.Xml.Serialization.XmlArrayItem("Table")> _ 
     Public Tables As New List(Of cTable) 

我想尝试的字符串改变为从字符串继承的自定义类,我可以用一个名称装备,但问题是,一个不能从字符串继承...

回答

0

你可以专门化字典模板或派生从专业化序列化,只要你想。

1

如果我正确地读你的问题,你想你的串行输出从:

<Tables> 
    <item> 
    <key> 
     <string>MyTable</string> 
    </key> 
    <value> 
     <!-- snip --> 
    </value> 
    </item> 
</Tables> 

为了这样的事情:

<Tables> 
    <item> 
    <key> 
     <TableId>MyTable</TableId> 
    </key> 
    <value> 
     <!-- snip --> 
    </value> 
    </item> 
</Tables> 

您也提到,一个办法可以实现这一点将创建自己的类型,从System.String继承,这 - 你也提到 - 显然是不可能的,因为它是sealed

默认情况下,XmlSerializer的 连载:

可以但是在自己的类型封装的键值,然后控制使用XmlTextAttribute(见MSDN)的XmlSerializer输出达到同样的效果作为XML 元素的类成员。但是,如果将 XmlTextAttribute应用于成员,则XmlSerializer将其值 转换为XML文本。这意味着 值被编码到XML元素的内容 中。

在你的情况,你会使用属性如下:

public class TableId 
{ 
    [XmlText] 
    public string Name 
    { 
     get; 
     set; 
    } 
} 

然后使用这种类型的键(一个或多个)您Dictionary。哪个应该达到你想要的。

0

尽管它可能有点偏离主题,但我需要问为什么使用XML来序列化它?如果你只是想保存未来的对象状态,我会建议使用JSON而不是XML。

一个很大的好处是你可以轻松地保存一个普通的Dictionary类而不必编写任何特殊的代码。由于JSON的有效载荷也小得多,所以如果需要的话,它可以通过线路发送。

Scott Gu有点关于使用JavascriptSerializer here的信息。我建议把它作为对象的扩展方法。那么你可以这样做:

Dictionary<int, string> myDict = new Dictionary<int,string>(); 
myDict.Add(10,"something"); 
string jsonData = myDict.ToJSON(); 

如果这是你有兴趣让我知道的事情,我可以张贴我使用的扩展方法的代码。 (没有工作,我没有在这里与我)

+0

首先,我限于.NET 2.0,和第二,主要的问题是,字典是一个通用型和不可序列(而不是在任一JSON)。我正在序列化为XML,因为XML使用更广泛,如果从.NET 2.0序列化,则更好阅读。 – 2010-07-30 11:21:56

0

既然你有源代码,你可以修改它,以便它查找XML属性,如果它们存在。关于XML的共享系列没有什么骶骨 - 就像其他任何可以通过反射查找的属性一样。一旦你有,你可以将新名称放入创建者的代码中并/或者读取XML标签。您也可以直接添加2个参数来显式重写标签名称,如ReadXml(myReader,“Tables”,“Table”),并将代码更改为遵循这些名称而不是默认值。必须切换到C#:-)

0

考虑用KeyedCollection替换字典。它被序列化为列表,因此它更小,XML节点名称是cTable属性/字段的名称。

[Serializable] 
[CollectionDataContract] 
public class TablesCollection : KeyedCollection<string, cTable> 
{ 
    protected override string GetKeyForItem(cTable item) 
    { 
     return item == null ? String.Empty : item.TableName; 
    } 
} 
0

不能说我用的是实现可序列化字典的,但如果你愿意尝试新的东西,有一个名为KeyedCollection一个鲜为人知的抽象类,这是完全可序列化,支持关键基于浏览器的访问,并可以很容易地实现为字典。

.Net 2.0 Keyed Collection