如何管理枚举的 XML 序列化异常

发布于 2024-12-05 14:39:01 字数 1235 浏览 1 评论 0原文

我正在使用 XML 序列化来生成特定于另一个应用程序的格式的文件。要求之一是所有布尔值都表示为 1 或 0。我研究了一些可能性,包括 struct 可以轻松无缝地处理此问题。目前我正在研究另一个场所,那就是使用枚举。

public enum BoolEnum
{
    [XmlEnum("0")]
    False = 0,
    [XmlEnum("1")]
    True = 1
}

到目前为止,它运行得非常好,而且更加干净。但是(!)我也试图使反序列化变得容易,并且我只是希望能够处理错误。如果我生成一个无效标记:

<invalid>2</invalid>

要反序列化为 BoolEnum,我会在另一个 InvalidOperationException 中收到 InvalidOperationException。我如何在枚举中捕获该异常?


附录:

反序列化函数:

static void Deserialize<T>(out T result, string sourcePath) where T : class
{
    FileStream fileStream = null;

    try
    {
        fileStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read);
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        result = xmlSerializer.Deserialize(fileStream) as T;
    }
    finally
    {
        if (fileStream != null)
            fileStream.Close();
    }
}

反序列化对象:

public class Test
{
    [XmlElement("someboolvalue")
    public BoolEnum SomeBoolValue { get; set; }
}

I'm using XML serialization to produce a file in a format specific to another application. One of the requirements is that all booleans be represented as 1 or 0. I've looked at some possibilities, including a struct to handle this easily and seamlessly. Currently I'm looking into another venue, which is to use an enum.

public enum BoolEnum
{
    [XmlEnum("0")]
    False = 0,
    [XmlEnum("1")]
    True = 1
}

So far, it works wonderfully, and it's much cleaner. BUT (!) I'm also trying to make the deserialization easy, and I'd just like to be able to handle errors. If I produce an invalid tag:

<invalid>2</invalid>

to be deserialized as BoolEnum, I get an InvalidOperationException inside another InvalidOperationException. How can I catch that exception in an enum?


Addendum:

Deserialization function:

static void Deserialize<T>(out T result, string sourcePath) where T : class
{
    FileStream fileStream = null;

    try
    {
        fileStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read);
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        result = xmlSerializer.Deserialize(fileStream) as T;
    }
    finally
    {
        if (fileStream != null)
            fileStream.Close();
    }
}

Deserialized object:

public class Test
{
    [XmlElement("someboolvalue")
    public BoolEnum SomeBoolValue { get; set; }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

再可℃爱ぅ一点好了 2024-12-12 14:39:01

我只是希望能够处理错误

您可以使用属性将某些属性公开给 Xml 序列化,并隐藏其他属性。同样,您可以通过智能感知将某些属性公开为可见,并隐藏其他属性。

您可以利用这一事实是使用与底层序列化不同的代码可见属性类型。这将允许您在代码中使用 bool ,并在序列化中使用 int

如果您选择此路线,则可以在 int 属性的 getter/setter 方法中添加自定义序列化代码来处理这种情况。例如

[XmlIgnore]
public bool SomeValue { get; set; }

[EditorBrowsable(EditorBrowsableState.Never)]
[XmlElement("SomeValue")]
public int SomeValueForSerialization
{
    get
    {
        return SomeValue ? 1 : 0;
    }
    set
    {
        SomeValue = value != 0;
        // Or do strict validation, and throw whatever exception you'd like.
        // Preferably one the serializer will already throw, tho :)
    }
}

I'd just like to be able to handle errors

You can use attributes to expose certain properties to Xml serialization, and hide other properties from it. Likewise you can expose certain properties to be visible via Intellisense, and hide others.

You can take advantage of this fact to use a different code-visible property type from the underlying serialization. This will allow you to use a bool in code, and an int in serialization.

If you choose this route, you can add custom serialization code to handle this case in the int property's getter/setter methods. E.g.

[XmlIgnore]
public bool SomeValue { get; set; }

[EditorBrowsable(EditorBrowsableState.Never)]
[XmlElement("SomeValue")]
public int SomeValueForSerialization
{
    get
    {
        return SomeValue ? 1 : 0;
    }
    set
    {
        SomeValue = value != 0;
        // Or do strict validation, and throw whatever exception you'd like.
        // Preferably one the serializer will already throw, tho :)
    }
}
七七 2024-12-12 14:39:01

我通常更喜欢将复杂的持久性保留为类的单独功能。

我使用 XElement 和扩展方法的组合来使持久性变得清晰和简洁,例如:

public static int AsZeroOrOneElelementNamed(this bool theBool, string name)
{
    return new XElement( name, theBool ? 1 : 0 ) ;
}

然后,在您的类型中:

public XElement AsXml( )
{
    return new XElement(@"ThisThing",
        _myBoolean.AsZeroOrElementNamed(@"MyBoolean"),
        _myString.AsElementNamed(@"MyString"));
}

这消除了 XML 属性的混乱,使内容更加清晰和简洁,并留下了唯一负责序列化的方法的持久性方面。

但是对于非常简单的持久性,例如,如果我不使用任何属性来混淆我的类型,那么我使用内置的持久性。

I generally prefer to keep complex persistence as a separate feature of a class.

I use a combination of XElement and extension methods to make persistence clear and concise, for example:

public static int AsZeroOrOneElelementNamed(this bool theBool, string name)
{
    return new XElement( name, theBool ? 1 : 0 ) ;
}

then, in your type:

public XElement AsXml( )
{
    return new XElement(@"ThisThing",
        _myBoolean.AsZeroOrElementNamed(@"MyBoolean"),
        _myString.AsElementNamed(@"MyString"));
}

This gets rid of the clutter of XML attributes which makes the clearer and cleaner and leaves the persistence aspect to a method who's only responsibility is serialisation.

But for very simple persistence, e.g. where I don't to clutter my types with any attributes, then I use the built in persistence.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文