序列化为 XML 并包含序列化对象的类型 [英] Serialise to XML and include the type of the serialised object

查看:29
本文介绍了序列化为 XML 并包含序列化对象的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在上一个关于在 C# 中将对象序列化为 XmlDocument 的问题中,我需要将一些错误信息序列化到从 asmx 样式的 web 服务调用返回的 XmlDocument.在客户端,我需要将 XmlDocument 反序列化回一个对象.

In a previous question about serialising an object to an XmlDocument in C#, I needed to serialise some fault information to an XmlDocument that was returned from a asmx-style webservice call. On the client I need to de-serialise the XmlDocument back to an object.

如果您知道类型,这很简单,但我意识到我想要一种灵活的方法,其中要反序列化的类型也在 XmlDocument 中编码.我目前通过将 XmlNode 添加到具有类型名称的 XmlDocument 来手动执行此操作,计算如下:

This is straightforward enough if you know the type, but I realised I wanted a flexible approach where the type to de-serialise to is also encoded in the XmlDocument. I'm currently doing it manually by adding an XmlNode to the XmlDocument that has the type name, calculated as follows:

    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 的类型对象,因此:

Then on the client I first get this type name back from the XmlDocument, and create the type object that is passed into the XmlSerialiser thus:

        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;

所以这是一种蛮力方法,我想知道是否有更优雅的解决方案,以某种方式自动包含序列化类型的类型名,而不是手动将其记录在其他地方?

So this is a brute-force approach, and I was wondering if there's a more elegant solution that somehow includes the typename of the serialised type automatically, rather than manually recording it elsewhere?

推荐答案

我遇到了类似的问题,我想出了相同的解决方案.就我而言,这是在 XML 序列化中将类型与值保持在一起的唯一方法.

I had faced a similar problem and I came up with the same solution. As far as I am concerned, that is the only way to keep types together with values in XML serialization.

我看到你也像我一样删除了汇编版本.但我想提一下,你会遇到泛型类型的问题,因为它们的签名看起来像这样:

I see you are cutting assembly version out as I did too. But I'd like to mention, that you will have troubles with generic types as theirs signature looks like that:

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

所以我做了一个函数来只剪切程序集版本,这似乎足以摆脱版本控制问题:

So I made a function to only cut out the assembly version(s), which seems to be enough to get rid of versioning problems:

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

这篇关于序列化为 XML 并包含序列化对象的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆