.net XML序列化继承类时出现InvalidOperationException

.net XML序列化继承类时出现InvalidOperationException,.net,xml,serialization,.net,Xml,Serialization,我在将c#类序列化为具有基类的XML文件时遇到了一个问题。。。下面是一个简单的例子: namespace Domain { [Serializable] public class ClassA { public virtual int MyProperty { get; set; } } } namespace Derived { public class ClassA : Domain.ClassA {

我在将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 */ }
      }
   }
}
当我尝试序列化派生.ClassA的实例时,收到以下异常:

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

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


这可能吗?如果可能,我如何赋予基类允许这样做?

我认为您的派生类也需要用
[Serializable]
属性标记才能序列化/反序列化

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


Marc

如果您可以随意将派生类重命名为与其基类不同的名称,则可以使用:

// 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);
这将序列化为
,并可以从中序列化为
ClassB
实例


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

为域设置一个基类名称空间,并为派生类设置一个自定义元素名称:

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;
            }
        }
    }
}

这对我们起了作用

[XmlType(TypeName = "DerivedClassA")] 

我也有同样的问题,但有一个附加的限制:无法访问域或派生类的源。派生对象继承自域对象,并且由于类具有相同的非限定名称,XmlSerializer将无法序列化派生类的对象

这可能已经用蛮力解决了(修改其中一个类的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());

即使您是域和/或派生类的作者,这样您也不需要重命名它们。

这只是提供信息,因为它没有提供具体的答案,但这里有一篇来自2003年7月MSDN期刊的好文章,讨论这些名称冲突。

感谢您的输入。问题是,我很少问问题,什么时候问我知道,他们通常都很难回答,我问的一个问题对我有帮助,但我还没有得到答案。那么我该怎么办呢?这确实是一个棘手的情况……你应该接受答案——但如果你没有得到任何有用的答案,很难选择一个来接受……我没有最终的答案……我同意……这并不是说我不知道我不想接受答案。同时,我不想接受答案只是说我接受了一个。我认为这违背了目的,改变了“接受”的含义“意思是,我试过了,但没用。还有别的吗?最终有效的解决方案与此类似,但没有那么复杂。您是正确的,.NET类名必须不同。。。不幸的是,.NET名称空间由于任何原因都没有被使用。因此,最简单的方法是为简单版本提供一个ClassABase,并将XmlRoot属性附加到ClassA的ClassABase上,然后使用名为ClassA的派生类。然后,它们都以相同的方式序列化。重写作为序列化程序的一部分,在不需要的地方。太好了!但这对从ClassABase派生的ClassB有效吗?还是只需要一个子类?
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());