可序列化字典,如何设置键名?

发布于 2024-09-09 10:24:04 字数 1955 浏览 6 评论 0原文

问题:我使用可序列化的字典类,位于 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)

我想尝试将 String 更改为从 string 继承的自定义类,我可以配备它一个名称,但问题是,不能从字符串继承......

Question: I use a serializable dictionary class, found at
http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx
, to serialize a dictionary.
Which works fine, but I run into an annoying problem.

      <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

When I serialize instances of the above class, as this,
the created xml looks like this:

<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>

Which would be good if only I could figure out how to rename the key from
<string> to something defined in an attribute

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

Basically something like the XmlArrayItem attribute, such as below, if (only) the dictionary were an array...

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

I wanted to try to change Of String to a custom class inherited from string, which I could equip with a name, but the problem is, one cannot inherit from string...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夜吻♂芭芘 2024-09-16 10:24:06

您可以专门化字典模板或从专门化派生以根据需要进行序列化。

You could specialize the Dictionary template or derive from a specialization to serialize as you want.

番薯 2024-09-16 10:24:06

虽然这可能有点偏离主题,但我需要问为什么使用 XML 来序列化它?如果您只想保存对象状态以供将来使用,我建议使用 JSON 而不是 XML。

一大好处是您可以轻松保存普通的 Dictionary 类,而无需编写任何特殊代码。有效负载也比 JSON 小得多,因此它是一种在需要时通过网络发送的绝佳格式。

Scott Gu 有一些关于使用 JavascriptSerializer 的信息 此处。我建议将其作为对象的扩展方法。然后您可以这样做:

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

如果您对此感兴趣,请告诉我,我可以发布我使用的扩展方法的代码。 (抱歉,我不在工作,我也没有带它们。)

Although it's probably somewhat off topic, I need to ask why use XML to serialize it? If you just want to save the object state for the future I would suggest JSON instead of XML.

One large benefit is you can easily save a normal Dictionary class without having to write any special code. The payload is also much smaller as JSON so it's a great format to send across the wire if needed.

Scott Gu has a bit of info about using the JavascriptSerializer here. I would suggest making it an extension method on object. Then you can do this:

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

If this is something your interested in let me know and I can post the code for the extension methods I use. (sry not at work and I don't have them with me here.)

她说她爱他 2024-09-16 10:24:06

由于您拥有源代码,因此您可以修改它,以便它查找 XML 属性(如果存在)。 XML 属性家族没有什么特别之处——它们就像任何其他可以通过反射查找的属性一样。一旦你有了这个,你就可以将新名称放入创建者的代码中和/或读取 XML 标签。您还可以仅添加 2 个参数来显式覆盖标记名称,例如 ReadXml(myReader, "Tables", "Table") 并更改代码以遵循这些名称而不是默认值。不过必须切换到 C# :-)

Since you have the source you can modify it so that it looks up XML attributes if they are present. There's nothign sacral about XML attribure family - the are just like any other attrib that can be looked up via reflection. Once yo u have that you can put new names into the code where in creater and/or reads XML tags. You can also just add 2 params to override tag names explicitly, like ReadXml(myReader, "Tables", "Table") and change the code to follow these names instead of defaults. Got to switch to C# though :-)

谁与争疯 2024-09-16 10:24:06

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

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

Consider replacing Dictionary with KeyedCollection. It is serialized as a list, as a result it is smaller and XML node names are names of cTable properties/fields.

[Serializable]
[CollectionDataContract]
public class TablesCollection : KeyedCollection<string, cTable>
{
    protected override string GetKeyForItem(cTable item)
    {
        return item == null ? String.Empty : item.TableName;
    } 
}
不乱于心 2024-09-16 10:24:06

不能说我已经使用了可序列化字典的实现,但是如果您愿意尝试新事物,有一个鲜为人知的抽象类,称为 KeyedCollection,它是完全可序列化的,支持基于键的访问,并且可以轻松地作为字典实现。

.Net 2.0 键控集合

can't say that i've used that implementation of serializeable dictionary, but in case you're willing to try new things, there is a little known abstract class called KeyedCollection which is fully serializeable, supports key based access, and can be easily implemented as dictionary.

.Net 2.0 Keyed Collection

暖阳 2024-09-16 10:24:05

如果我正确地阅读您的问题,您希望将序列化输出从以下位置更改为:

<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,正如您也提到的那样,这显然是不可能的,因为它是密封的

不过,您可以通过将键值封装在您自己的类型中,然后使用 XmlTextAttribute 控制 XmlSerializer 输出来实现相同的结果(请参阅< a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmltextattribute.aspx" rel="nofollow noreferrer">MSDN):

默认情况下,XmlSerializer
将类成员序列化为 XML
元素。但是,如果您应用
XmlTextAttribute 为成员,
XmlSerializer 转换其值
转换为 XML 文本。这意味着
值被编码到内容中
一个 XML 元素。

在您的情况下,您将按如下方式使用该属性:

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

然后使用此类型作为 Dictionary 的键。这应该能达到你想要的效果。

If I'm reading your question correctly, you want to change your serialized output from this:

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

To something like this:

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

You also mention that one way you could achieve this would be to create your own type which inherited from System.String, which - as you also mention - obviously isn't possible because it's sealed.

You can however achieve the same result by encapsulating the key value in your own type, and then controlling the XmlSerializer output using an XmlTextAttribute (see MSDN):

By default, the XmlSerializer
serializes a class member as an XML
element. However, if you apply the
XmlTextAttribute to a member, the
XmlSerializer translates its value
into XML text. This means that the
value is encoded into the content of
an XML element.

In your case you'd use the attribute as follows:

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

And then use this type as the key(s) to your Dictionary. Which should achieve what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文