.NET двоичный XML с предварительно общим словарем

Я использую XmlDictionaryWriter для сериализации объектов в базе данных с помощью сериализатора контрактов данных. Он отлично работает, размер и скорость в 2 раза лучше, чем при использовании text / xml.

Однако мне придется иметь дело с огромным количеством записей в моей базе данных, где любые лишние байты напрямую переводятся в гигабайты Размер БД. Вот почему я хотел бы еще больше уменьшить размер, используя словарь XML.

Как мне это сделать?

Я вижу, что статический метод XmlDictionaryWriter.CreateBinaryWriter принимает 2-й параметр типа IXmlDictionary. В MSDN говорится: «Словарь XmlDictionary для использования в качестве общего словаря».

Сначала я попытался использовать реализацию, поставляемую системой:

XmlDictionary dict = new XmlDictionary();
string[] dictEntries = new string[]
{
    "http://schemas.datacontract.org/2004/07/MyContracts",
    "http://www.w3.org/2001/XMLSchema-instance",
    "MyElementName1",
    "MyElementName2",
    "MyElementName3",
};
foreach ( string s in dictEntries )
        dict.Add( s );

В результате .NET framework полностью игнорирует словарь и по-прежнему вставляет указанные выше строки как простой текст, а не просто ссылка на соответствующую запись словаря.

Затем я создал свою собственную реализацию IXmlDictionary:

class MyDictionary : IXmlDictionary
{
    Dictionary<int, string> values = new Dictionary<int, string>();
    Dictionary<string, int> keys = new Dictionary<string, int>();

    MyDictionary()
    {
        string[] dictEntries = new string[]
        {
            "http://schemas.datacontract.org/2004/07/MyContracts",
            "http://www.w3.org/2001/XMLSchema-instance",
            "MyElementName1",
            "MyElementName2",
            "MyElementName3",
        };

        foreach ( var s in dictEntries )
            this.Add( s );
    }

    static IXmlDictionary s_instance = new MyDictionary();
    public static IXmlDictionary instance { get { return s_instance; } }

    void Add( string val )
    {
        if ( keys.ContainsKey( val ) )
            return;
        int id = values.Count + 1;
        values.Add( id, val );
        keys.Add( val, id );
    }

    bool IXmlDictionary.TryLookup( XmlDictionaryString value, out XmlDictionaryString result )
    {
        if ( value.Dictionary == this )
        {
            result = value;
            return true;
        }
        return this.TryLookup( value.Value, out result );
    }

    bool IXmlDictionary.TryLookup( int key, out XmlDictionaryString result )
    {
        string res;
        if ( !values.TryGetValue( key, out res ) )
        {
            result = null;
            return false;
        }
        result = new XmlDictionaryString( this, res, key );
        return true;
    }

    public bool /* IXmlDictionary. */ TryLookup( string value, out XmlDictionaryString result )
    {
        int key;
        if ( !keys.TryGetValue( value, out key ) )
        {
            result = null;
            return false;
        }

        result = new XmlDictionaryString( this, value, key );
        return true;
    }
}

В результате - мои методы TryLookup вызываются ОК, однако DataContractSerializer.WriteObject создает пустой документ.

Как мне использовать общий словарь?

Заранее спасибо!

PS Я не Я не хочу возиться с XmlBinaryReaderSession / XmlBinaryWriterSession: у меня нет «сеансов», вместо этого у меня есть база данных размером 10 ГБ, к которой одновременно обращаются многие потоки. Я хочу только статический предопределенный словарь.

Обновление: Хорошо, я понял, что мне просто нужно вызвать «XmlDictionaryWriter.Flush». Остается только один вопрос - почему реализация IXmlDictionary, поставляемая системой, не работает должным образом?

8
задан Soonts 14 March 2011 в 19:20
поделиться