Сериализация в XML и включение типа сериализованного объекта - PullRequest
4 голосов
/ 05 мая 2009

В предыдущем вопросе о сериализации объекта в XmlDocument в C # мне нужно было сериализовать некоторую информацию об ошибках в XmlDocument, которая была возвращена из вызова веб-службы asmx-стиля. На клиенте мне нужно десериализовать XmlDocument обратно к объекту.

Это достаточно просто, если вы знаете тип, но я понял, что мне нужен гибкий подход, при котором тип для десериализации также кодируется в XmlDocument. В настоящее время я делаю это вручную, добавив XmlNode к XmlDocument, который имеет имя типа, вычисляемое следующим образом:

    Type type = fault.GetType();
    string assemblyName = type.Assembly.FullName;

    // Strip off the version and culture info
    assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(",")).Trim();

    string typeName = type.FullName + ", " + assemblyName;

Затем на клиенте я сначала получаю это имя типа из XmlDocument и создаю объект типа, который передается в XmlSerialiser таким образом:

        object fault;
        XmlNode faultNode = e.Detail.FirstChild;
        XmlNode faultTypeNode = faultNode.NextSibling;

        // The typename of the fault type is the inner xml of the first node
        string typeName = faultTypeNode.InnerXml;
        Type faultType = Type.GetType(typeName);

        // The serialised data for the fault is the second node
        using (var stream = new StringReader(faultNode.OuterXml))
        {
            var serialiser = new XmlSerializer(faultType);
            objectThatWasSerialised = serialiser.Deserialize(stream);
        }

        return (CastToType)fault;

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

Ответы [ 2 ]

3 голосов
/ 05 мая 2009

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

Я вижу, вы вырезали версию сборки, как я тоже. Но я хотел бы отметить, что у вас будут проблемы с родовыми типами, так как их подпись выглядит так:

System.Nullable`1[[System.Int, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Итак, я сделал функцию, чтобы вырезать только версию (и) сборки, которая, по-видимому, достаточна для устранения проблем с версиями:

    private static string CutOutVersionNumbers(string fullTypeName)
    {
        string shortTypeName = fullTypeName;
        var versionIndex = shortTypeName.IndexOf("Version");
        while (versionIndex != -1)
        {
            int commaIndex = shortTypeName.IndexOf(",", versionIndex);
            shortTypeName = shortTypeName.Remove(versionIndex, commaIndex - versionIndex + 1);
            versionIndex = shortTypeName.IndexOf("Version");
        }
        return shortTypeName;
    }
0 голосов
/ 05 мая 2009

Нейл, зачем вам это должно быть одинакового типа как на клиенте, так и на сервере?

Вы все еще используете ASMX на клиенте? Это было бы причиной, поскольку ASMX не поддерживает должным образом ошибки.

Кроме того, у вас так много разных типов ошибок, что простой оператор switch не может определить правильный тип для использования?

...