programing

XmlInclude 또는 SoapInclude 특성을 사용하여 정적으로 알 수 없는 유형을 지정합니다.

javamemo 2023. 9. 17. 12:03
반응형

XmlInclude 또는 SoapInclude 특성을 사용하여 정적으로 알 수 없는 유형을 지정합니다.

일을 할 때 아주 이상한 문제가 생겼습니다.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
}

AFAIK, 3가지 다른 해결 방법이 있습니다.InvalidOperationException그건 연쇄 살인범이 그들의 유형에 대해 알지 못하기 때문에 발생하는 것입니다.Payment.

1. 추가하기XmlInclude에게Payment클래스 정의:

이것은 내가 통제할 수 없는 외부 참조로 모든 클래스가 포함되어 있기 때문에 불가능합니다.

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

적절한XmlSerializer생성자가 사용됩니다.

메모: 작동하지 않는다는 것은.InvalidOperationException(예상하지 못했습니다...)가 던져집니다.BankPayment

누가 그 문제를 좀 설명해 줄 수 있습니까?그 문제를 어떻게 해결하고 더 이상 디버그할 것입니까?

효과가 있었습니다.

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

방금 문제를 해결했습니다.한참을 더 뒤적거리다가 똑같은 상황을 다루는 SO 게시물을 발견했습니다.제가 옳은 길을 걷게 해줬습니다.

기본적으로.XmlSerializer파생 클래스가 추가 유형으로 포함된 경우 기본 네임스페이스를 알아야 합니다.이런 일이 발생해야 하는 정확한 이유는 아직 알 수 없지만, 지금도 직렬화가 작동하고 있습니다.

를 바탕으로 저는 이를 해결할 수 있었습니다.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();
}

내가 한 짓은

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

그냥 베이스에서 하면 어떤 아이라도 코드 클리너 코드를 줄이지 않고 직렬화할 수 있습니다.

public abstract class XmlBaseClass  
{
  public virtual string Serialize()
  {
    this.SerializeValidation();

    XmlSerializerNamespaces XmlNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
    XmlWriterSettings XmlSettings = new XmlWriterSettings
    {
      Indent = true,
      OmitXmlDeclaration = true
    };

    StringWriter StringWriter = new StringWriter();

    XmlSerializer Serializer = new XmlSerializer(this.GetType());
    XmlWriter XmlWriter = XmlWriter.Create(StringWriter, XmlSettings);
    Serializer.Serialize(XmlWriter, this, XmlNamespaces);
    StringWriter.Flush();
    StringWriter.Close();

    return StringWriter.ToString();

  }

  protected virtual void SerializeValidation() {}
}

[XmlRoot(ElementName = "MyRoot", Namespace = "MyNamespace")]
public class XmlChildClass : XmlBaseClass
{
  protected override void SerializeValidation()
  {
    //Add custom validation logic here or anything else you need to do
  }
}

이렇게 하면 상황에 상관없이 하위 클래스에서 Serialize를 호출하고 개체 Serialize 전에 필요한 작업을 수행할 수 있습니다.

비즐에 동의합니다.

[XmlInclude(typeof(ParentOfTheItem))]
[Serializable]
public abstract class WarningsType{ }

또한 만약 당신이 이 포함된 클래스를 객체 아이템에 적용해야 한다면 그렇게 할 수 있습니다.

[System.Xml.Serialization.XmlElementAttribute("Warnings", typeof(WarningsType))]
public object[] Items
{
    get
    {
        return this.itemsField;
    }
    set
    {
        this.itemsField = value;
    }
}

추가했습니다.[System.Xml.Serialization.XmlAttributeAttribute()]재산에 관해서는 저를 위해 해결했습니다.

언급URL : https://stackoverflow.com/questions/11886290/use-the-xmlinclude-or-soapinclude-attribute-to-specify-types-that-are-not-known

반응형