使用可以是不同枚举类型的通用枚举序列化一个类 [英] Serializing a class with a generic Enum that can be different Enum types

查看:168
本文介绍了使用可以是不同枚举类型的通用枚举序列化一个类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计一个允许用户在XML中指定Enum类型的应用程序,并且应用程序将执行与该枚举绑定的特定方法(使用字典)。我正在挂起XML的枚举部分。

I'm trying to design an application that will allow the user to specify an Enum type in an XML, and from that the application will execute a specific method tied to that enum (using a dictionary). I'm getting hung up on the Enum portion of the XML.

public class TESTCLASS
{
    private Enum _MethodType;

    [XmlElement(Order = 1, ElementName = "MethodType")]
    public Enum MethodType
    {
        get { return _MethodType; }
        set { _MethodType = value; } 
    }
    public TESTCLASS() { }

    public TESTCLASS(Enummies.BigMethods bigM)
    {
        MethodType = bigM;
    }
    public TESTCLASS(Enummies.SmallMethods smallM)
    {
        MethodType = smallM;
    }
}

public class Enummies
{
    public enum BigMethods { BIG_ONE, BIG_TWO, BIG_THREE }
    public enum SmallMethods { SMALL_ONE, SMALL_TWO, SMALL_THREE }
}

然后尝试序列化TESTCLASS导致异常:

And then trying to serialize the TESTCLASS results in an exception:

string p = "C:\\testclass.xml";
TESTCLASS testclass = new TESTCLASS(Enummies.BigMethods.BIG_ONE);
TestSerializer<TESTCLASS>.Serialize(p, testclass);

System.InvalidOperationException: The type Enummies+BigMethods may not be used in this context.

我的序列化方法如下所示:

My serialization method looks like this:

public class TestSerializer<T> where T: class
{
    public static void Serialize(string path, T type)
    {
        var serializer = new XmlSerializer(type.GetType());
        using (var writer = new FileStream(path, FileMode.Create))
        {
            serializer.Serialize(writer, type);
        }
    }

    public static T Deserialize(string path)
    {
        T type;
        var serializer = new XmlSerializer(typeof(T));
        using (var reader = XmlReader.Create(path))
        {
            type = serializer.Deserialize(reader) as T;
        }
        return type;
    }
}

我尝试在MethodType Getter中包含一些检查/转换,但这会导致相同的错误。

I tried including some checking/casting in the MethodType Getter, but this results in the same error.

    public Enum MethodType
    {
        get 
        { 
            if (_MethodType is Enummies.BigMethods) return (Enummies.BigMethods)_MethodType; 
            if (_MethodType is Enummies.SmallMethods) return (Enummies.SmallMethods)_MethodType;
            throw new Exception("UNKNOWN ENUMMIES TYPE");
        }
        set { _MethodType = value; } 
    }


推荐答案

当我尝试序列化您的课程与 XmlSerializer ,我得到的最内部的异常是:

When I try to serialize your class with XmlSerializer, the innermost exception I get is:

Message="System.Enum is an unsupported type. Please use [XmlIgnore] attribute to exclude members of this type from serialization graph."

这是不言而喻的:您不能序列化类型为抽象类型的成员 System.Enum

This is self-explanatory: you cannot serialize a member whose type is the abstract type System.Enum.

但是,您可以将类型为 System.Object 的成员序列化,前提是所有可能的类型可能遇到的价值是通过使用 [XmlInclude(typeof(T))] 因此,您可以按照以下方式修改您的类型:

You can, however, serialize a member of type System.Object provided that all possible types of value that might be encountered are declared statically by using [XmlInclude(typeof(T))]. Thus you can modify your type as follows:

// Include all possible types of Enum that might be serialized
[XmlInclude(typeof(Enummies.BigMethods))]
[XmlInclude(typeof(Enummies.SmallMethods))]
public class TESTCLASS
{
    private Enum _MethodType;

    // Surrogate object property for MethodObject required by XmlSerializer
    [XmlElement(Order = 1, ElementName = "MethodType")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public object MethodTypeObject
    {
        get { return MethodType; }
        set { MethodType = (Enum)value; }
    }

    // Ignore the Enum member that cannot be serialized directly
    [XmlIgnore]
    public Enum MethodType
    {
        get { return _MethodType; }
        set { _MethodType = value; }
    }
    public TESTCLASS() { }

    public TESTCLASS(Enummies.BigMethods bigM)
    {
        MethodType = bigM;
    }
    public TESTCLASS(Enummies.SmallMethods smallM)
    {
        MethodType = smallM;
    }
}

XML将生成如下:

<TESTCLASS xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <MethodType xsi:type="BigMethods">BIG_THREE</MethodType>
</TESTCLASS>

<?xml version="1.0" encoding="utf-16"?>
<TESTCLASS xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <MethodType xsi:type="SmallMethods">SMALL_TWO</MethodType>
</TESTCLASS>

注意 xsi:type 属性?这是一个 W3C标准属性,元素可能用于明确声明其类型。 Microsoft使用此属性来表示多态元素的类型信息,如 here 所述

Notice the xsi:type attribute? That is a W3C standard attribute that an element may use to explicitly assert its type. Microsoft uses this attribute to represent type information for polymorphic elements as explained here.

示例小提琴

您可能需要检查值类型是否为 MethodObject 中的已知枚举 code>(而不是getter),但这不是XML序列化所必需的。

You might want to check that the value type is a known Enum type in the setter for MethodObject (rather than the getter) but this is not required for XML serialization.

这篇关于使用可以是不同枚举类型的通用枚举序列化一个类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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