none
XML сериализация List<object> RRS feed

  • Общие обсуждения

  • Если в List<object> содержатся строки, числа и т.п., то проблем нет, но если занести туда массив, к примеру, строк, то при сериализации получаем ошибку
    System.InvalidOperationException: Ошибка при создании документа XML. ---> System.InvalidOperationException: Тип "System.Collections.Generic.List`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]" не может использоваться в этом контексте.
    Соответственно вопрос - можно ли как-то сериализовать List<object>, если его элементами могут являться массивы?
    • Изменен тип I.Vorontsov 2 ноября 2009 г. 8:09 Вопрос перешёл в обсуждения
    • Перемещено Siddharth Chavan 1 октября 2010 г. 21:53 MSDN Forums Consolidation (От:Visual C#)
    25 октября 2009 г. 12:14

Все ответы

  • Вы используете XmlArray и XmlArrayItem атрибуты?
    26 октября 2009 г. 9:43
  •             string[] str1 = { "one", "two" };
                string[] str2 = { "three", "four" };
    
                List<string[]> lst = new List<string[]>();
                lst.Add(str1);
                lst.Add(str2);
    
                XmlSerializer ser = new XmlSerializer(typeof(List<String[]>));
                StreamWriter sw = new StreamWriter(@"c:\test.xml");
                ser.Serialize(sw, lst);
                sw.Close();
    //-----------------------------------------------------------------------
    PS C:\> type test.xml
    <?xml version="1.0" encoding="utf-8"?>
    <ArrayOfArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <ArrayOfString>
        <string>one</string>
        <string>two</string>
      </ArrayOfString>
      <ArrayOfString>
        <string>three</string>
        <string>four</string>
      </ArrayOfString>
    </ArrayOfArrayOfString>
    Всё работает, или я не правильно вас понял?
    26 октября 2009 г. 10:44
  • OlegGel , нет,  надо именно список объектов, то есть я не знаю, какие элементы в нем будут. В общем, надо что работало вот это )
    private void button1_Click(object sender, EventArgs e)
    {
    	List<object> wildArray = new List<object>();
    	List<string> strings = new List<string>();
    
    	strings.Add("qqq");
    	wildArray.Add(strings);
    
    	XmlSerializer serializer = new XmlSerializer(wildArray.GetType());
    
    	using (TextWriter tw = new StreamWriter(@"c:\tmp.txt", false, Encoding.Default))
    	{
    		serializer.Serialize(tw, wildArray);
    	}
    }
    26 октября 2009 г. 11:48
  • I.Vorontsov , нет, создаю сериализатор без этих параметров. Постом ниже пример.
    26 октября 2009 г. 11:49
  • А, ну понятно, у вас список ссылок на объекты object ,а компилятор не знает поддерживают эти объекты сериализацию или нет. Вам нужно в цикле каждый элемент внешнего списка приводить к конкретному типу списка внутреннего и сериализовать их. Конечно, это имхо.
    26 октября 2009 г. 12:07
  • Просто если я в список заношу, к примеру, строки, числа, DateTime - то все сериализуется нормально и в итоговой xml-ке типы определены корректно.
    26 октября 2009 г. 12:46
  • Соответственно вопрос - можно ли как-то сериализовать List<object>, если его элементами могут являться массивы?
    Можно ли объединить переменные для данной задачи в структуру?
    Если не смотреть на корявость кода, сделал бы так:
    public struct MyStruct
            {
                public List<object> wildArray;
                public List<string> strings;
            }
            private MyStruct TestMyClass = new MyStruct();
            private void button1_Click(object sender, EventArgs e)
            {
                 TestMyClass.strings = new List<string>();
                 TestMyClass.wildArray = new List<object>();
    
                 TestMyClass.strings.Add("qqq");
                 TestMyClass.wildArray.Add(TestMyClass.strings);
                 System.IO.FileStream fs;
                 System.Xml.Serialization.XmlSerializer xmlS = new System.Xml.Serialization.XmlSerializer(typeof(MyStruct));
                 fs = new System.IO.FileStream(@"с:\tmp.txt", System.IO.FileMode.Create);
                 xmlS.Serialize(fs, TestMyClass);
                 fs.Close();
            }

    29 октября 2009 г. 18:08
  • Проблема в том, что массивов и других объектов может быть сколько угодно, один список строк я взял просто для примера. И фишка именно в том, что List<object> как раз хранит все эти неизвестные объекты.
    30 октября 2009 г. 11:50
  • XmlSerializer - это не только сериализатор, это еще и десериализатор. Если у него заранее нет полного списка возможных типов, то он просто не сможет десериализовать список. Например, какого поведения ты ожидаешь при десериализации
    <MyArray>
       <TestClass></TestClass>
       <SomeObject123></SomeObject123>
    </MyArray>
    TestClass - из какой сборки? Что делать, если таких типов несколько, в разных пространствах имен?

    Можно заранее перечислить поддерживаемые типы с помощью аттрибута XmlArrayItem . Если полного списка поддерживаемых типов нет на момент компиляции, но есть на момент сериализации/десериализации, то можно задать их динамически через XmlAttributeOverrides
    Но сериализовать и десериализовать вообще все что угодно не получится.
    30 октября 2009 г. 14:29
  • А так не пойдёт?
    Объекты нормально вкладываются, правда xml будет выглядеть несколько "не очень"...

    public struct MyStruct
            {
                public List<object> wildArray;
                public List<string> strings;
            }
            private MyStruct TestMyClass = new MyStruct();
            private void btnSave_Click(object sender, EventArgs e)
            {
                TestMyClass.strings = new List<string>();
                TestMyClass.wildArray = new List<object>();
                List<object> testList = new List<object>();
                List<object> testList2 = new List<object>();
                List<object> testList3 = new List<object>();
                List<object> testList4 = new List<object>();
                List<object> testList5 = new List<object>();
                testList.Add("a");
                testList.Add("s");
                testList.Add("d");
                testList.Add("e");
                testList2.Add("f");
                testList2.Add(testList);
                
                testList3.Add(testList);
                testList3.Add(testList2);
                testList4.Add(testList3);
                testList5.Add(testList4);
                TestMyClass.strings.Add("qqq");
                TestMyClass.wildArray.Add(TestMyClass.strings);
                TestMyClass.wildArray.Add(testList2);
                TestMyClass.wildArray.Add(testList);
                TestMyClass.wildArray.Add(testList3);
                TestMyClass.wildArray.Add(testList4);
                TestMyClass.wildArray.Add(testList5);
                System.IO.FileStream fs;
                System.Xml.Serialization.XmlSerializer xmlS = new System.Xml.Serialization.XmlSerializer(typeof(MyStruct));
                fs = new System.IO.FileStream(@"d:\temp\tmp.txt", System.IO.FileMode.Create);
                xmlS.Serialize(fs, TestMyClass);
                fs.Close();
            }
    
            private void btnLoad_Click(object sender, EventArgs e)
            {
                System.IO.FileStream fs;
                System.Xml.Serialization.XmlSerializer xmlS = new
                    System.Xml.Serialization.XmlSerializer(typeof(MyStruct));
    
                fs = new System.IO.FileStream(@"d:\temp\tmp.txt", System.IO.FileMode.Open);
                TestMyClass = (MyStruct)xmlS.Deserialize(fs);
                fs.Close();
            }
    30 октября 2009 г. 16:46

  • Вопрос немного не по теме - какой смысл сохранять в xml "сколько угодно массивов и других объектов" с заранее неизвестной структурой? Ведь при этом получится такой же непредсказуемый xml-документ, который нельзя будет использовать. Потому что все, что о нем известно - в нем есть "теги, аттрибуты и вообще какие угодно ноды".
    30 октября 2009 г. 19:55
  • Ну смысл в том что иногда действительно не знаешь, что нужно будет сохранить. Например, пользователь сгенерироваи иерархию объектов которую нужно передать на веб-сервер чтобы там хранить в sql с использованием hierarchyid - а для этого нужно уметь эту структуру сериализовать.
    - Dmitri Nesteruk
    31 октября 2009 г. 5:50
  • Не представляю себе веб-сервер, который сможет сохранить в sql c использованием hierarchyid вообще какой угодно заранее неизвестный xml. В этой структуре наверняка будет заранее известный набор классов и вполне известных связей, а не "массивы массивов каких угодно объектов". Если типы известны на момент создания сериализатора - то XmlArrayItem решает проблему. Но топикастер ждет что XmlSerializer сам о типах объектов догадается.
    31 октября 2009 г. 9:12
  • Смысл прост и банален - создать универсальный класс настроек, куда бы можно было сохранять любые сериализуемые объекты )
    Попробую вариант с XmlAttributeOverride .
    31 октября 2009 г. 9:58
  • С этой задачей неплохо справляется система параметров приложения
    31 октября 2009 г. 10:15