Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Странности с XmlWriter.Create


Автор: diadiavova 2.2.2015, 14:18
Столкнулся со странной проблемой. Создал XmlTextWriter с помощью конструктора для сериализации объекта. Все работало нормально, только текст был не отформатирован. Как работать с этим классом немного подзабыл, но помнил, что есть объект Settings, начал его "мучать, оказалось, что он недоступен для изменения. Потом проблему решил, но до этого, выяснил, что задать собственные настройки можно только создавая экземпляр райтера с помощью метода Create. Все экземпляры, которые я создавал, используя разные перегрузки этого метода, приводили к одному и тому же результату - пустой строке. Здесь хочу заметить, что работал этот объект с тем же самым кодом, в котором экземпляр, созданный с помощью конструктора справился на ура. Что не так с "креэйтом"?

Автор: Ilya81 2.2.2015, 15:06
А где http://referencesource.microsoft.com/#System.Xml/System/Xml/Core/XmlWriterSettings.cs,c5df69ed1afb635e напрямую вызывается конструктор для XmlTextWriter? Возможно, в других классах просто что-то переопределено.

Автор: diadiavova 2.2.2015, 15:32
Цитата(Ilya81 @  2.2.2015,  15:06 Найти цитируемый пост)
А где здесь напрямую вызывается конструктор для XmlTextWriter? Возможно, в других классах просто что-то переопределено. 

Честно говоря, я твоего ответа не понял. Как этот пример объясняет, почему созданный с помощью конструктора экземпляр работает, а с помощью креэйт - нет? smile 

Автор: Ilya81 2.2.2015, 16:35
В смысле, что метод Create создаёт, вероятно, другие классы, не XmlTextWriter, а, например, какой-нибудь XmlUtf8RawTextWriter. А в этом классе, вероятно, что-то иначе. 

P. S. Не помню уже по какому поводу, но мне как-то раньше доводилось смотреть эти исходники (в смысле класса XmlWriter).

Автор: diadiavova 2.2.2015, 16:48
Ilya81, а как это может повлиять на то, что он вообще никакого выхлопа не дает. Ведь как я себе представляю процесс сериализации: сериалайзер получает райтер и вызывает последовательно его методы, попутно передавая ему аргументы. При этом ему по барабану, какой именно подтип ему передали, поскольку он работает с интерфейсом базового класса. Теперь, если экземпляр получен, его методы вызваны, то это должно каким-то образом отобразиться на результате или должно вылететь какое-то исключение в конце концов. К тому же, если я передаю методу креэйт теткстрайтер или стрингбилдер (а я пробовал оба варианта), то мне лично тоже как-то пофиг, какой будет райтер, но текст он просто обязан туда сбросить. Хрен с ним, пусть он будет в другой кодировке или хотя бы выбросит исключение, но он не делает ни того ни другого, а просто возвращает пустую строку. Если бы мой код не работал, с райтером, созданным с помощью конструктора, то я бы на код подумал, но тут хрень какая-то получается.

Автор: diadiavova 2.2.2015, 17:21
Для большей наглядности выкладыаю пример.

Автор: Ilya81 3.2.2015, 09:15
Я-то думал, речь идёт о XmlSerializer'а, а не DataContractSerializer'е - про последний не очень знаю, но так и так - я в таких случаях предпочитаю подключить исходники framework'а и заглянуть в них отладчиком - часто после этого становится понятно.

Автор: diadiavova 3.2.2015, 10:41
Цитата(Ilya81 @  3.2.2015,  09:15 Найти цитируемый пост)
Я-то думал, речь идёт о XmlSerializer'а, а не DataContractSerializer'е - про последний не очень знаю

А что это меняет? Добавил в код еще и его, тот райтер, который создан с помощью креэйт вывалил исключение, другой - отработал нормально.
Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Serialization;
namespace xmlwriterexample
{
 
    [DataContract]
    public class Person
    {
        [DataMember]
       public string Name { get; set; }
        [DataMember]
       public string SecondName { get; set; }
        [DataMember]
       public string Surname { get; set; }

    }
    class Program
    {
        static void Main(string[] args)
        {
            var serializer = new DataContractSerializer(typeof(Person));
            var xserializer = new XmlSerializer(typeof(Person));
            var builder = new StringBuilder();
            using (var writer = new System.IO.StringWriter(builder))
            {
                var xmlwriterNew = new XmlTextWriter(writer);
                var xmlwriterCreate = XmlWriter.Create(writer);
                var person = new Person() { Name = "Иван", SecondName = "Иванович", Surname = "Иванов" };
                builder.AppendLine("Результат работы райтера, созданного конструктором");
                serializer.WriteObject(xmlwriterNew, person);
                builder.AppendLine();
                builder.AppendLine("Результат работы райтера, созданного Create");
                serializer.WriteObject(xmlwriterCreate, person);
                builder.AppendLine("Результат работы райтера, созданного конструктором и XmlSerializer");
                xserializer.Serialize(xmlwriterNew, person);
                builder.AppendLine("Результат работы райтера, созданного Create и XmlSerializer");
                //xserializer.Serialize(xmlwriterCreate, person);
                
                Console.WriteLine(builder.ToString());

            }
            Console.ReadKey();
        }
    }
}

Строка с исключением закомментирована.
Цитата(Ilya81 @  3.2.2015,  09:15 Найти цитируемый пост)
но так и так - я в таких случаях предпочитаю подключить исходники framework'а и заглянуть в них отладчиком - часто после этого становится понятно. 

Видимо придется. Просто проект не на C# пишется и эта функция там недоступна, но теперь есть на чем колдовать.  smile 

Автор: diadiavova 3.2.2015, 11:34
Ну с исключением справился, благодаря добавлению settings, в котором установил ConformanceLevel.Auto. На датаконтрактсериалайзер это действия не возымело. Ну да ладно. smile 

Автор: diadiavova 3.2.2015, 14:34
Отформатировал и малость подкрасил вывод и оказалось, что при использовании хмлсериалайзера с райтером, созданным при помощи креэйт, хмл почему-то продублировался, видимо сериалайзер отработал и за себя за своего датаконтракт-собрата. Короче с этим креэйтом точно что-то не так smile 
Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Serialization;
namespace xmlwriterexample
{

    [DataContract]
    public class Person
    {
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string SecondName { get; set; }
        [DataMember]
        public string Surname { get; set; }

    }
    class Program
    {
        static void Main(string[] args)
        {
            var serializer = new DataContractSerializer(typeof(Person));
            var xserializer = new XmlSerializer(typeof(Person));
            var xmlwriterNew = new XmlTextWriter(Console.Out);
            xmlwriterNew.Formatting = Formatting.Indented;
            var settings = new XmlWriterSettings();
            settings.ConformanceLevel = ConformanceLevel.Fragment;
            settings.OmitXmlDeclaration = false;
            settings.Indent = true;
            var xmlwriterCreate = XmlWriter.Create(Console.Out, settings);
            var person = new Person() { Name = "Иван", SecondName = "Иванович", Surname = "Иванов" };
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Результат работы райтера, созданного конструктором");
            Console.ForegroundColor = ConsoleColor.White;
            serializer.WriteObject(xmlwriterNew, person);
            Console.WriteLine();
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Результат работы райтера, созданного Create");
            Console.ForegroundColor = ConsoleColor.White;
            serializer.WriteObject(xmlwriterCreate, person);
            Console.WriteLine();
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Результат работы райтера, созданного конструктором и XmlSerializer");
            Console.ForegroundColor = ConsoleColor.White;
            xserializer.Serialize(xmlwriterNew, person);
            Console.WriteLine();
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Результат работы райтера, созданного Create и XmlSerializer");
            Console.ForegroundColor = ConsoleColor.White;
            xserializer.Serialize(xmlwriterCreate, person);
            Console.ReadKey();
        }

    }
}


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)