C# 如何 XML 序列化“类型”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/290867/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 21:53:25  来源:igfitidea点击:

How to XML Serialize a 'Type'

c#xmlserialization

提问by Robert

How do I serialize a 'Type'?

如何序列化“类型”?

I want to serialize to XML an object that has a property that is a type of an object. The idea is that when it is deserialized I can create an object of that type.

我想将具有对象类型的属性的对象序列化为 XML。这个想法是,当它被反序列化时,我可以创建一个该类型的对象。

public class NewObject
{
}

[XmlRoot]
public class XmlData
{
    private Type t;

    public Type T
    {
        get { return t; }
        set { t = value; }
    }
}
    static void Main(string[] args)
    {
        XmlData data = new XmlData();
        data.T = typeof(NewObject);
        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(XmlData));
            try
            {
                using (FileStream fs = new FileStream("test.xml", FileMode.Create))
                {
                    serializer.Serialize(fs, data);
                }
            }
            catch (Exception ex)
            {

            }
        }
        catch (Exception ex)
        {

        }
    }

I get this exception: "The type ConsoleApplication1.NewObject was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."

我收到此异常:“不需要类型 ConsoleApplication1.NewObject。使用 XmlInclude 或 SoapInclude 属性指定静态未知的类型。”

Where do I put the [XmlInclude]? Is this even possible?

我把 [XmlInclude] 放在哪里?这甚至可能吗?

采纳答案by CSharper

XML serialization serializes only the public fields and property values of an object into an XML stream. XML serialization does not include type information.For example, if you have a Book object that exists in the Library namespace, there is no guarantee that it will be deserialized into an object of the same type.

XML 序列化仅将对象的公共字段和属性值序列化为 XML 流。XML 序列化不包括类型信息。例如,如果您有一个 Book 对象存在于 Library 命名空间中,则不能保证它会被反序列化为相同类型的对象。

Source: MSDN: Introducing XML Serialization

来源:MSDN:介绍 XML 序列化

回答by Filip Fr?cz

You could potentially implement the IXmlSerializableinterface and use Type.FullName(you may also need Type.AssemblyQualifiedName) for serialization and the Assembly.GetType(string)for deserialization of your type element.

您可能会实现IXmlSerializable接口并使用Type.FullName(您可能还需要Type.AssemblyQualifiedName)用于序列化和Assembly.GetType(string)类型元素的反序列化。

回答by Robert

I ended up converting the Type name to a string to save it to XML.

我最终将类型名称转换为字符串以将其保存为 XML。

When deserializing, I load all the DLLs and save the name of the type and type in a dictionary. When I load the XML with the Type Name, I can look up the name in the dictionary key and know the type based on the dictionary value.

反序列化时,我加载所有 DLL 并将类型和类型的名称保存在字典中。当我加载带有类型名称的 XML 时,我可以在字典键中查找名称并根据字典值知道类型。

回答by Robert Wagner

The problem is that the type of XmlData.T is actually "System.RuntimeType" (a subclass of Type), which unfortunately is not public. This means there is no way of telling the serialise what types to expect. I suggest only serializing the name of the type, or fully qualified name as Jay Bazuzi suggests.

问题在于 XmlData.T 的类型实际上是“System.RuntimeType”(Type 的子类),不幸的是它不是公开的。这意味着无法告诉序列化期望什么类型。我建议只序列化类型的名称,或者像 Jay Bazuzi 建议的那样完全限定名称。

回答by Mikael

Ugly but it works. Make a Class which includes the object type and the serialized string.

丑陋,但它的工作原理。创建一个包含对象类型和序列化字符串的类。

ex

前任

Class dummie
{
    Type objType;
    string xml;
}

回答by TheSean

Typeclass cannot be serialized because System.RuntimeTypeis not accessible to our code, it is an internal CLR type. You may work around this by using the type's name instead, like this:

Type类无法序列化,因为System.RuntimeType我们的代码无法访问它,它是内部 CLR 类型。您可以通过使用类型名称来解决此问题,如下所示:

public class c 
{       
    [XmlIgnore]
    private Type t;
    [XmlIgnore]
    public Type T {
        get { return t; }
        set { 
                t = value;
                tName = value.AssemblyQualifiedName;
            }
    }

    public string tName{
        get { return t.AssemblyQualifiedName; }
        set { t = Type.GetType(value);}
    }
}