Сериализуемый словарь, как определить ключевое имя?

Вопрос: Я использую сериализуемый класс словаря, найденный по http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx, для сериализации словаря. Который хорошо работает, но я сталкиваюсь с раздражающей проблемой.

       _
    Public Class cDataBase
         _
        Public ns As New System.Xml.Serialization.XmlSerializerNamespaces()


         _
        Public Tables1 As New SerializableDictionary(Of String, cTable)


    End Class ' cDataBase

Когда я сериализирую экземпляры вышеупомянутого класса, поскольку это, созданный xml похож на это:



  
    MyTable
  
  
    
        
          Uniqueidentifier
          36
        
      
        
          Reihe1
          Reihe2
          Reihe3
        
        
          Reihe1
          Reihe2
          Reihe3
        

Который был бы хорош, если только я мог бы выяснить, как переименовать ключ от <строки> до чего-то определенного в атрибуте

  
    MyTable
  

В основном что-то как атрибут XmlArrayItem, такой как ниже, если (только) словарь был массивом...

         _
         _
        Public Tables As New List(Of cTable)

Я хотел попробовать к изменению Строки к пользовательскому классу, наследованному от строки, которую я мог оборудовать именем, но проблема, нельзя наследоваться строке...

7
задан Stefan Steiger 16 July 2010 в 11:22
поделиться

6 ответов

Вы можете специализировать шаблон Dictionary или получить производную от специализации для сериализации, как вам нужно.

0
ответ дан 7 December 2019 в 20:33
поделиться

Если я правильно читаю ваш вопрос, вы хотите изменить свой сериализованный вывод следующим образом:

<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 , что, как вы также упомянули, очевидно, невозможно, потому что оно запечатано .

Вы можете достичь того же результата, инкапсулируя значение ключа в свой собственный тип, а затем управляя выводом XmlSerializer с помощью XmlTextAttribute (см. MSDN ):

По умолчанию XmlSerializer сериализует член класса как XML элемент. Однако если вы примените XmlTextAttribute для члена, XmlSerializer переводит свое значение в текст XML. Это означает, что значение закодировано в содержании элемент XML.

В вашем случае вы должны использовать атрибут следующим образом:

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

А затем использовать этот тип в качестве ключа (ов) к вашему Словарю . Который должен достичь того, чего вы хотите.

1
ответ дан 7 December 2019 в 20:33
поделиться

Поскольку у вас есть источник, вы можете изменить его, чтобы он выполнял поиск атрибутов XML, если они есть. В семействе атрибутов XML нет ничего сакрального - они такие же, как и любые другие атрибуты, которые можно найти с помощью отражения. Как только вы это сделаете, вы можете добавить новые имена в код, где он будет создавать и / или читать теги XML. Вы также можете просто добавить 2 параметра для явного переопределения имен тегов, например ReadXml (myReader, «Таблицы», «Таблица»), и изменить код, чтобы он следовал этим именам вместо значений по умолчанию. Однако нужно перейти на C #: -)

0
ответ дан 7 December 2019 в 20:33
поделиться

Хотя это, вероятно, несколько не по теме, я должен спросить, зачем использовать XML для его сериализации? Если вы просто хотите сохранить состояние объекта на будущее, я бы предложил JSON вместо XML.

Одним из больших преимуществ является то, что вы можете легко сохранить обычный класс Dictionary без необходимости писать какой-либо специальный код. Полезная нагрузка также намного меньше, чем JSON, поэтому при необходимости это отличный формат для отправки по сети.

У Скотта Гу есть небольшая информация об использовании JavascriptSerializer здесь . Я бы посоветовал сделать это методом расширения объекта. Затем вы можете сделать это:

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

Если вас это интересует, дайте мне знать, и я могу опубликовать код для методов расширения, которые я использую. (извините, не на работе, а их здесь нет.)

0
ответ дан 7 December 2019 в 20:33
поделиться

Рассмотрите возможность замены Dictionary на 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
ответ дан 7 December 2019 в 20:33
поделиться

не могу сказать, что я использовал эту реализацию сериализуемого словаря, но на случай, если вы захотите попробовать что-то новое, есть малоизвестный абстрактный класс под названием KeyedCollection, который полностью сериализуем, поддерживает доступ на основе ключей и может быть легко реализован в виде словаря.

.Net 2.0 Keyed Collection

0
ответ дан 7 December 2019 в 20:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: