2012-05-08 15 views
1

これに決定的な応答を見つけることができないと私は夢中です。 XmlSerializerクラスは、定義されているものやネストされたクラスのものであっても有効です。しかし、クラスの1つにSystem.Objectが含まれていると、それが嘔吐します。誰もがこの周りの簡単な方法を知っていますか?System.Objectオブジェクトを持つXmlSerializer

namespace test 
{ 
    public class SomeList 
    { 
     public object obj; 
    } 

    public class Person 
    { 
     public string first; 
     public string last; 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       Console.WriteLine("Creating object..."); 
       Person me = new Person(); 
       me.first = "MyFirst"; 
       me.last = "MyLast"; 

       Console.WriteLine("- Serialized: " + serialize_xml<Person>(me)); 
       Console.WriteLine(""); 
       Console.WriteLine("Creating object with embedded generic..."); 
       SomeList test = new SomeList(); 
       test.obj = me; 
       Console.WriteLine("- Serialized: " + serialize_xml<SomeList>(test)); 

       Console.WriteLine(""); 
       Console.Write("Press ENTER to exit."); 
       Console.ReadLine(); 
       return; 
      } 
      catch (Exception e) 
      { 
       print_exception(e); 
       Console.WriteLine(""); 
       Console.Write("Press ENTER to exit."); 
       Console.ReadLine(); 
       return; 
      } 
     } 

     static string serialize_xml<T>(T obj) 
     { 
      XmlSerializer xmls = new XmlSerializer(typeof(T)); 
      using (MemoryStream ms = new MemoryStream()) 
      { 
       XmlWriterSettings settings = new XmlWriterSettings(); 
       XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
       ns.Add("", ""); 

       settings.Encoding = Encoding.UTF8; 
       settings.Indent = false; 
       settings.NewLineChars = ""; 
       settings.NewLineHandling = NewLineHandling.None; 
       settings.NewLineOnAttributes = false; 
       settings.ConformanceLevel = ConformanceLevel.Document; 
       settings.OmitXmlDeclaration = true; 

       using (XmlWriter writer = XmlTextWriter.Create(ms, settings)) 
       { 
        xmls.Serialize(writer, obj, ns); 
       } 

       string xml = Encoding.UTF8.GetString(ms.ToArray()); 

       // remove the BOM character at the beginning which screws up decoding 
       if (xml.Length > 0 && xml[0] != '<') 
       { 
        xml = xml.Substring(1, xml.Length - 1); 
       } 
       return xml; 
      } 
     } 

     static void print_exception(Exception e) 
     { 
      Console.WriteLine(" = Exception Type: " + e.GetType().ToString()); 
      Console.WriteLine(" = Exception Dat " + e.Data); 
      Console.WriteLine(" = Inner Exception: " + e.InnerException); 
      Console.WriteLine(" = Exception Message: " + e.Message); 
      Console.WriteLine(" = Exception Source: " + e.Source); 
      Console.WriteLine(" = Exception StackTrace: " + e.StackTrace); 
     } 
    } 
} 

は、コンソールに次の出力を作成します。

= Exception Type: System.InvalidOperationException 
= Exception Dat System.Collections.ListDictionaryInternal 
= Inner Exception: System.InvalidOperationException: The type test.Person was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically. 
    at System.Xml.Serialization.XmlSerializationWriter.WriteTypedPrimitive(String name, String ns, Object o, Boolean xsiType) 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSomeList.Write1_Object(String n, String ns, Object o, Boolean isNullable, Boolean needType) 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSomeList.Write2_SomeList(String n, String ns,SomeList o, Boolean isNullable, Boolean needType) 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSomeList.Write3_SomeList(Object o) 
= Exception Message: There was an error generating the XML document. 
= Exception Source: System.Xml 
= Exception StackTrace: at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id) 
    at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces) 
    at test.Program.serialize_xml[T](T obj) in C:\Users\jchristn\Documents\Visual Studio 2010\Projects\test\test\Program.cs:line 83 
    at test.Program.Main(String[] args) in C:\Users\jchristn\Documents\Visual Studio 2010\Projects\test\test\Program.cs:line 47 
+2

AFAIKは、XmlSerializerが実行時に認識できるデータ型のみをシリアル化できることを認識しています。 Object型を追加すると、この期待を破ります。おそらく、あなたはObjectを使うべきではありませんが、Interfaceの型を使うべきでしょう。 – CodingBarfield

答えて

5

あなたは、コンテナ上でそれらを指定することができ、オブジェクトSomeList.objの固定セットを含めることができますがありますと仮定すると、そのセットは、コンパイル時に知られており、 XmlIncludeAttributeを使用してクラス:タイプはコンパイル時に知られていない場合

[XmlInclude(typeof(Person))] 
[XmlInclude(typeof(Other))] 
public class SomeList 
{ 
    public object obj; 
} 

public class Person 
{ 
    public string first; 
    public string last; 
} 

public class Other 
{ 
    public int MyProperty { get; set; } 
} 

、あなたはの配列を指定することができますXmlSerializerコンストラクタのオーバーロードの種類:

XmlSerializer xmls = new XmlSerializer(typeof(T), new Type[] { <...types...> }); 
関連する問題