XML序列化继承类时出现InvalidOperationException

时间:2009-10-12 17:09:33

标签: .net xml serialization

我在将c#类序列化为具有基类的XML文件时出现问题...这是一个简单的例子:

namespace Domain
{
   [Serializable]
   public class ClassA
   {
      public virtual int MyProperty
      {
         get; set;
      }
   }
}

namespace Derived
{
   public class ClassA : Domain.ClassA
   {
      public override int MyProperty
      {
         get { return 1; } set { /* Do Nothing */ }
      }
   }
}

当我尝试序列化Derived.ClassA的一个实例时,我收到以下异常:

InvalidOperationException(Types'Domain.ClassA'和'Derived.ClassA'都使用来自命名空间的XML类型名称'ClassA'。使用XML属性为该类型指定唯一的XML名称和/或命名空间。)

问题是我想创建一个简单定义XML文件结构的基类,然后允许其他任何人从该类派生来插入业务规则,但格式化将来自基础

这是可能的,如果是这样,我如何将基类归因于允许这个?

6 个答案:

答案 0 :(得分:5)

这对我们起了作用。

[XmlType(TypeName = "DerivedClassA")] 

答案 1 :(得分:2)

如果您可以将派生类重命名为与其基类不同的内容,则可以使用XmlAttributeOverrides执行此操作:

// For ClassB, which derives from ClassA
XmlAttributes          attributes  = new XmlAttributes();                        
attributes.XmlRoot                 = new XmlRootAttribute("ClassA");

XmlAttributeOverrides  overrides   = new XmlAttributeOverrides();
overrides.Add(typeof(ClassB), attributes);

XmlSerializer   serializer  = new XmlSerializer(typeof(ClassB), overrides);

这将序列化为<ClassA> ... </ClassA>,并可以将其序列化为ClassB个实例。

据我所知,当基类和派生类具有相同的名称时(除了通过Data Contract Surrogates或其他一些过度杀伤方法完全控制序列化过程之外),没有办法做到这一点。 / p>

答案 2 :(得分:0)

我认为你的派生类还需要用[Serializable]属性标记为可序列化/可反序列化。

除了serializable属性之外,您还需要使两者中的一个具有不同的XML名称 - 正如错误所述,在“XML world”中,它们都被称为“ClassA”。其中一个必须使用XmlElement属性进行不同的命名(假设您正在使用XmlSerializer - 对吗?)

namespace Domain
{
   [Serializable]
   [XmlElement(ElementName="ClassABase")]
   public class ClassA
   {
      public virtual int MyProperty
      {
         get; set;
      }
   }
}

namespace Derived
{
   [Serializable]
   public class ClassA : Domain.ClassA
   {
      public override int MyProperty
      {
         get { return 1; } set { /* Do Nothing */ }
      }
   }
}

马克

答案 3 :(得分:0)

为您的域设置基本命名空间,并为派生类设置自定义元素名称:

namespace Domain
{
    [Serializable]
    [XmlRoot(Namespace = "http://mynamespace/domain/2009/")]
    public class ClassA
    {
        [XmlIgnore]
        public virtual int MyProperty { get; set; }
    }
}

namespace Derived
{
    [Serializable]
    [XmlRoot(ElementName = "DerivedClassA")]
    public class ClassA : Domain.ClassA
    {
        public override int MyProperty
        {
            get
            {
                return 1;
            }
            set
            {
                base.MyProperty = value;
            }
        }
    }
}

答案 4 :(得分:0)

我遇到了同样的问题,但有一个额外的限制:无法访问Domain或Derived类的源代码。从Domain对象继承的Derived对象,并且由于这些类具有相同的非限定名称,XmlSerializer将无法序列化Derived类的对象。

这可能已经用蛮力解决了(修改其中一个类的IL以添加适当的属性),但我想要一些“更干净”的东西。这是有效的:

var attrs = new XmlAttributes();
attrs.XmlType = new XmlTypeAttribute("anythingButClassA");

var overrides = new XmlAttributeOverrides();
overrides.Add(typeof(Domain.ClassA), attrs);

var serializer = new XmlSerializer(typeof(Derived.ClassA), overrides);
serializer.Serialize(Console.Out, new Derived.ClassA());

即使您是Domain和/或Derived类的作者,也不需要重命名它们。

答案 5 :(得分:0)

这只是提供信息,因为它没有提供具体的答案,但这是2003年7月MSDN问题讨论这些名称冲突的好文章。 "XML Namespace Collisions, XmlNodeList and Deserialization, and More"