使用XmlInclude或SoapInclude属性指定静态未知的类型

lso*_*ira 83 .net c# xml xmlserializer

使用.NET时,我遇到了一个非常奇怪的问题XmlSerializer.

采用以下示例类:

public class Order 
{
    public PaymentCollection Payments { get; set; }

    //everything else is serializable (including other collections of non-abstract types)
}

public class PaymentCollection : Collection<Payment>
{
}

public abstract class Payment 
{
    //abstract methods
}

public class BankPayment : Payment
{
    //method implementations
}
Run Code Online (Sandbox Code Playgroud)

AFAIK,有三种不同的方法可以解决InvalidOperationException由序列化程序不知道派生类型引起的问题Payment.

1.添加XmlIncludePayment类定义:

这是不可能的,因为所有类都包含在我无法控制的外部引用中.

2.在创建XmlSerializer实例期间传递派生类型的类型

不行.

3.定义XmlAttributeOverrides目标属性以覆盖属性的默认序列化(如本SO帖子中所述)

也不起作用(XmlAttributeOverrides初始化如下).

Type bankPayment = typeof(BankPayment);

XmlAttributes attributes = new XmlAttributes();
attributes.XmlElements.Add(new XmlElementAttribute(bankPayment.Name, bankPayment));

XmlAttributeOverrides overrides = new XmlAttributeOverrides();
overrides.Add(typeof(Order), "Payments", attributes);
Run Code Online (Sandbox Code Playgroud)

XmlSerializer然后将使用适当的构造函数.

注意:by 不起作用我的意思是InvalidOperationException(BankPayment不是预期的......)被抛出.

任何人都可以对这个问题有所了解吗?如何进一步调试问题?

biz*_*izl 81

这对我有用:

[XmlInclude(typeof(BankPayment))]
[Serializable]
public abstract class Payment { }    

[Serializable]
public class BankPayment : Payment {} 

[Serializable]
public class Payments : List<Payment>{}

XmlSerializer serializer = new XmlSerializer(typeof(Payments), new Type[]{typeof(Payment)});
Run Code Online (Sandbox Code Playgroud)

  • 那么基类型需要知道它的所有实现吗?这似乎不是一个很好的解决方案.没有其他办法吗? (12认同)
  • @AlexanderStolz用于在创建XmlSerializable对象时传递新Type的泛型实现是最佳解决方案.如上所述http://stackoverflow.com/a/2689660/698127 (2认同)

lso*_*ira 37

刚解决了这个问题.经过一段时间的挖掘后,我发现这个SO帖子涵盖了完全相同的情况.它让我走上正轨.

基本上,如果派生类被包含为额外类型,则XmlSerializer需要知道默认命名空间.这种情况发生的确切原因尚不清楚,但是,序列化现在仍然有效.


der*_*can 5

基于此,我能够通过更改XmlSerializer我正在使用的构造函数而不是更改类来解决这个问题。

而不是使用这样的东西(在其他答案中建议):

[XmlInclude(typeof(Derived))]
public class Base {}

public class Derived : Base {}

public void Serialize()
{
    TextWriter writer = new StreamWriter(SchedulePath);
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Derived>));
    xmlSerializer.Serialize(writer, data);
    writer.Close();
}
Run Code Online (Sandbox Code Playgroud)

我这样做了:

public class Base {}

public class Derived : Base {}

public void Serialize()
{
    TextWriter writer = new StreamWriter(SchedulePath);
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Derived>), new[] { typeof(Derived) });
    xmlSerializer.Serialize(writer, data);
    writer.Close();
}
Run Code Online (Sandbox Code Playgroud)