2016-06-17 3 views
0

フォーク、XMLでのコントロール要素C#シリアライゼーション

いくつかの異なるクラスタイプにまたがる要素で基本クラスを作成しようとしています。私は解決策に近いですが、私はXMLシリアライザクラスからの出力をより詳細に制御する必要があります。

UPDATE


I下記の回答に基づいてOK]をクリックして、XMLのためにSerializableインタフェースを追加して、ビットさらに持っています。

以下は、私の新しいテストAPPの出力です。期待される最初の2つのXML出力です.3番目は近いですが、ルート要素に名前空間がなく、SomeNewNameForPDataがPDataのように動作する必要があります。示された最後のXMLのようなPDataは明白ではなく、また、Base Request ClassからApplicationを失っています。予想される出力の最終例を参照してください。

<?xml version="1.0" encoding="utf-8"?> 
<Payment1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Application="MyApp"> 
    <Pdata Language="en"> 
    <TimeStamp>2016-06-17T15:31:37.7767381+01:00</TimeStamp> 
    </Pdata> 
    <RequestType>Pay1</RequestType> 
</Payment1> 

<?xml version="1.0" encoding="utf-8"?> 
<Payment2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Application="MyApp"> 
    <Sender>ProgramClass</Sender> 
    <RequestType>Pay2</RequestType> 
</Payment2> 

<?xml version="1.0" encoding="utf-8"?> 
<Payment3> 
    <SomeNewNameForPData> 
    <P_Data Language="en"> 
     <TimeStamp>2016-06-17T15:31:37.7767381+01:00</TimeStamp> 
    </P_Data> 
    </SomeNewNameForPData> 
</Payment3> 

予想される出力:

<?xml version="1.0" encoding="utf-8"?> 
<Payment3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Application="MyApp"> 
    <SomeNewNameForPData Language="en"> 
     <TimeStamp>2016-06-17T15:31:37.7767381+01:00</TimeStamp> 
    </SomeNewNameForPData> 
</Payment3> 

更新されたコード:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Xml.Serialization; 
using System.IO; 
using System.ComponentModel; 
using System.Xml; 

namespace ConsoleApplication7 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Request cp = new Payment1() { Application = "MyApp", DataField = new P_Data() { Language = "en" } }; 

      Request cp2 = new Payment2() { Application = "MyApp", Sender = "ProgramClass" }; 

      Request cp3 = new Payment3() { Application = "MyApp", DataField = new P_Data() { Language = "en" } }; 

      string s1 = cp.MessageAsString(); 

      string s2 = cp2.MessageAsString(); 

      string s3 = cp3.MessageAsString(); 

      Console.WriteLine(s1); 
      Console.WriteLine(""); 
      Console.WriteLine(s2); 
      Console.WriteLine(""); 
      Console.WriteLine(s3); 

      Console.ReadKey(); 
     } 
    } 

    public class Helpers : StringWriter 
    { 
     public override Encoding Encoding 
     { 
      get { return Encoding.UTF8; } 
     } 
    } 

    public abstract class Request 
    { 
     [XmlAttribute()] 
     public string Application { get; set; } 

     public virtual string MessageAsString() 
     { 
      return CreateMessage(); 
     } 

     private string CreateMessage() 
     { 
      return SerializeObject<Request>(this, null); 
     } 

     public static string SerializeObject<X>(X toSerialize, XmlSerializerNamespaces xmlNameSpace) 
     { 
      XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType()); 
      StringWriter textWriter = new StringWriter(); 

      string utf8 = ""; ; 
      using (StringWriter writer = new Helpers()) 
      { 
       xmlSerializer.Serialize(writer, toSerialize, xmlNameSpace); 
       utf8 = writer.ToString(); 
      } 

      return utf8; 
     } 

    } 

    public abstract class RequestType1 : Request 
    { 
     public RequestType1() 
     { 
     } 

     [XmlIgnore()] 
     public abstract string RequestType { get; set; } 

     [XmlElement("Pdata")] 
     public virtual P_Data DataField { get; set; } 
    } 

    public abstract class RequestType2 : Request 
    { 
     public RequestType2() 
     { 
     } 

     [XmlIgnore()] 
     public abstract string RequestType { get; set; } 

     public string Sender { get; set; } 
    } 

    [Serializable] 
    public abstract class RequestType3 : RequestType1, IXmlSerializable 
    { 
     public RequestType3() 
     { 
     } 

     [XmlElement("SomeNewNameForPData")] 
     public override P_Data DataField { get; set; } 

     public System.Xml.Schema.XmlSchema GetSchema() 
     { 
      throw new NotImplementedException(); 
     } 

     public void ReadXml(XmlReader reader) 
     { 
      throw new NotImplementedException(); 
     } 

     public void WriteXml(XmlWriter writer) 
     { 
      writer.WriteStartElement("SomeNewNameForPData"); 

      var ns = new XmlSerializerNamespaces(); 
      ns.Add("", ""); 
      new XmlSerializer(typeof(P_Data)).Serialize(writer, this.DataField, ns); 

      writer.WriteEndElement(); 
     } 
    } 

    public class Payment1 : RequestType1 
    { 
     public Payment1() 
     { 
     } 

     public override string RequestType 
     { 
      get 
      { 
       return "Pay1"; 
      } 
      set { } 

     } 
    } 

    public class Payment2 : RequestType2 
    { 
     public Payment2() 
     { 
     } 

     public override string RequestType 
     { 
      get 
      { 
       return "Pay2"; 
      } 
      set { } 

     } 
    } 

    public class Payment3 : RequestType3 
    { 
     public Payment3() 
     { 
     } 

     public override string RequestType 
     { 
      get 
      { 
       return "Pay3"; 
      } 
      set { } 

     } 
    } 

    public class P_Data 
    { 
     public P_Data() 
     { 
      //We need to format the datetime field 
      TimeStamp = DateTime.Now; 
     } 

     [XmlAttribute, DefaultValue("")] 
     public string Language { get; set; } 

     public DateTime TimeStamp { get; set; } 
    } 
} 

だから私の質問は以下のとおりです。ルート要素で名前空間を追加したり、保存する方法

  1. クストー使用時のお支払い3 m WriteXmlメソッドは、私はまた、基本クラスの項目を書くための手段を提供する必要がありますか、私は、そのタイプに基づいてXmlSerializerを使用してクラスをシリアル化しているという事実によってこれらを取得しないのですか?私はそれがパラレルデータPDataであるかのように行動するSomeNewNameForPDataが必要

  2. は、何のパラレルデータPDataは

  3. 明らか基本要求クラスからのアプリケーションに戻って追加しないすなわち。

TIA

+0

あなたは説明できます''ノードを表示するには? –

+0

私は、RequestまたはRequestType2に存在する可能性がある異なるClaasesのためにプラホルダとしてノードを使用しています。したがって、このNODEのリストは、サードパーティが必要とするものに応じて異なるクラスに追加されます。ノードクラスでは、存在する可能性があるすべての要素を指定します。これはデモ目的で問題を説明するためのサブセットです。 –

答えて

1

あなたが得ることができる最も近いです:

<MyRequestName Sender="MyAppName" IP="123.456.7.0"> 
    <NodeWhatever> 
    <BaseElement type="SomeData" LanguageCode="en" /> 
    <BaseElement type="SomeOtherData" Amount="1000" /> 
    </NodeWhatever> 
</MyRequestName> 

なぜ?複数のノードがある場合は、元のオブジェクトを再作成する方法がないため、どの基本要素がどのノードに属しているかを調べる方法がないためです。これはあなたが望むものであるならば、あなたの更新質問で

public abstract class Root 
{ 

    public string Sender { get; set; } 


    public string IP { get; set; } 

    [Persist("", ChildName = "NodeWhatever")] 
    public List<Node> Nodes { get; set; } 
} 

[PersistInclude(typeof(SomeData),typeof(SomeOtherData))] 
public class Node 
{ 
    [Persist("")] 
    public List<BaseElement> Elements { get; set; } 
} 

XmlArchive serial = new XmlArchive(R.GetType()); 
Archive.ClassKwd = "type"; 

string utf8 = ""; ; 

using (var mm = new MemoryStream()) 
{ 
    serial.Write(mm,R,"MyRequestName"); 
    mm.Position = 0; 

    using (var reader = new StreamReader(mm)) 
    { 
     utf8 = reader.ReadToEnd(); 
    } 
} 

Console.WriteLine(utf8);  

私はわからないこのXMLを、得ることができます:

<Payment1 RequestType="Pay1" Application="MyApp"> 
    <DataField Language="en" TimeStamp="06/17/2016 10:38:39" /> 
</Payment1> 

<Payment2 RequestType="Pay2" Sender="ProgramClass" Application="MyApp" /> 

<Payment3 RequestType="Pay3" Application="MyApp"> 
    <MyNameWhatever Language="en" TimeStamp="06/17/2016 10:38:39" /> 
</Payment3> 

コード:あなたがしたくない理由

public abstract class Request 
{ 
    public string Application { get; set; } 

    public virtual string MessageAsString() 
    { 
     return CreateMessage(); 
    } 

    private string CreateMessage() 
    { 
     return SerializeObject<Request>(this); 
    } 

    public static string SerializeObject<X>(X toSerialize) 
    { 
     var xmlSerializer = new XmlArchive(toSerialize.GetType()); 
     Archive.Provider = CultureInfo.InvariantCulture; 

     string utf8 = ""; ; 
     using (var writer = new MemoryStream()) 
     { 
      xmlSerializer.Write(writer, toSerialize); 
      writer.Position = 0; 

      var reader = new StreamReader(writer); 
      utf8 = reader.ReadToEnd(); 
     } 

     return utf8; 
    } 

} 

public abstract class RequestType1 : Request 
{ 
    public abstract string RequestType { get; set; } 
    public virtual P_Data DataField { get; set; } 
} 

public abstract class RequestType2 : Request 
{   
    public abstract string RequestType { get; set; } 
    public string Sender { get; set; } 
} 


public abstract class RequestType3 : RequestType1 
{ 
    [Persist("MyNameWhatever")] 
    public override P_Data DataField { get; set; } 

} 

public class Payment1 : RequestType1 
{ 
    public override string RequestType 
    { 
     get { return "Pay1"; } 
     set { } 
    } 
} 

public class Payment2 : RequestType2 
{ 
    public override string RequestType 
    { 
     get { return "Pay2"; } 
     set { } 
    } 
} 

public class Payment3 : RequestType3 
{ 
    public override string RequestType 
    { 
     get { return "Pay3"; } 
     set { } 
    } 
} 

public class P_Data 
{ 
    public P_Data() { TimeStamp = DateTime.Now; } 
    public string Language { get; set; } 
    public DateTime TimeStamp { get; set; } 
} 
+0

おかげでelios、私はそれ以来、私は新しいコードで元のポストを更新して、私は他の場所で読んでいた同様のコメントに基づいて別の方法に行ってきました。 –

関連する問題