【问题标题】:Instance validation error: * is not a valid value for *实例验证错误:* 不是 * 的有效值
【发布时间】:2014-04-10 08:00:10
【问题描述】:

我正在尝试反序列化一个 XML 字符串,其中元素的值不在我的 Enum 值的范围内。

Public enum MyEnum
{
    Unknown,
    Car,
    Bicycle,
    Boat
}

[SerializableAttribute()]
public class MyClass
{
    private string _id;
    private MyEnum _myEnum;

    public string ID
    {
        get { return _id; }
        set { _id = value; }
    }

    public MyEnum EnumValue
    {
        get { return _myEnum; }
        set { _myEnum = value; }
    }

    public MyClass(string id)
    {
        this._id = id;
    }

    public MyClass() : this("") { }
}

如果我尝试反序列化以下字符串(注意 Plane 作为枚举值):

<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><MyClass><ID>1234567890123456789</ID><EnumValue>Plane</EnumValue></MyClass>

然后我的反序列化将抛出一个异常,甚至在它到达我的 EnumValue 的公共字段之前,并带有以下异常消息:

实例验证错误:'Plane' 不是 EnumValue 的有效值

如果我尝试在 XML 中解析的值不支持作为 EnumValue,是否可以返回 EnumValue 的默认值? 例如。对于此处提供的 XML 字符串,EnumValue 应设置为“未知”。

【问题讨论】:

    标签: c# xml-deserialization


    【解决方案1】:

    是的,但我认为你不能再使用 SerializableAttribute 了。

    您应该实现 ISerializable 并提供您自己的序列化器/反序列化器。您可以使用默认的序列化程序(例如 new BinaryFormatter().serializer()),但您必须实现自定义反序列化。

    【讨论】:

      【解决方案2】:

      其他方法是将 EnumValue 声明为字符串并将 EnumValue 属性中的值解析为另一个属性中的 MyEnum(使用自定义逻辑)。另一个属性应标记为不可序列化。

      public string EnumValue
      {
          get { return _myEnum; }
          set { _myEnum = value; }
      }
      
      [NonSerialized]
      public MyEnum EnumValueTyped {
        get {
          MyEnum value;
          if (Enum.TryParse<MyEnum>(EnumValue, out value)) {
            return value;
          }
          return MyEnum.Unknown;
        }
        set {
          EnumValue = value.ToString();
        }
      }
      

      【讨论】:

        【解决方案3】:
        [XmlIgnore]
        public MyEnum EnumValueReal
        {
            get { return _myEnum; }
            set { _myEnum = value; }
        }
        
        public string EnumValue
        {
             get
             {
                 return EnumValueReal.ToString();
             }
        
             set
             {
                 MyEnum result = MyEnum.Unknown;
                 Enum.TryParse(value, true, out result);
        
                 EnumValueReal = result;
             }
        }
        

        【讨论】:

        • EnumValue 将被序列化,它允许保留违反 MyEnum 限制的值。同时 EnumValueReal 可以处理违反约束的情况。这不是被问到的问题吗?
        • 对不起。我的错。我刚刚看到 EnumValueReal 中提到了 XmlIgore。没看EnumValue。再次抱歉。 (+1)
        • 以这个解决方案结束,但没有创建一个带有 XmlIgnore 标记的公共 MyEnum 字段,因为 MyClass.cs 中的私有 MyEnum myEnum 无论如何都不会被序列化。将枚举转换为字符串是我的解决方案。谢谢。
        【解决方案4】:

        有时发生的情况是我们在对项目进行更改后不更新 dll 或我们在项目中引用的项目,因此不会检测到添加/删除的参数,从而引发相同的问题。因此最好采用更新的 dll 并继续。可能是一个愚蠢的错误,但经常犯。一切顺利:)

        【讨论】:

          【解决方案5】:

          恕我直言,最“合适”的解决方案是使 EnumValue 属性可为空 - 因为您得到的错误(和 MyEnum.Unknown)意味着该属性可能没有值...

          代码如下所示:

          public enum MyEnum
          {
              Car,
              Bicycle,
              Boat
          }
          
          [Serializable()]
          public class MyClass
          {
              private string _id;
              private MyEnum? _myEnum;
          
              public string ID
              {
                  get { return _id; }
                  set { _id = value; }
              }
          
              public MyEnum? EnumValue
              {
          
                  get { return _myEnum; }
                  set { _myEnum = value; }
              }
          
              public MyClass(string id)
              {
                  this._id = id;
              }
          
              public MyClass() : this("")
              {
              }
          }
          

          【讨论】:

          • 这并不能完全解决问题,不。
          猜你喜欢
          • 2012-06-14
          • 1970-01-01
          • 1970-01-01
          • 2015-11-03
          相关资源
          最近更新 更多