Глубокий xml сериализует параметры структуры

У меня есть класс и структура, показанные ниже. Если я сериализую класс как использует xmlserializer, я получаю:

<Тест>
<TestNumber1> 5 </ TestNumber1>
<InnerTest />
</ Тест>

каков самый простой способ правильно сериализовать InnerTest (желательно с использованием xmlserializer) без указания свойству Number a сеттер?

Спасибо, Ник

public class Test 
{ 
    private InnerTest innerTest; 
    private int testNumber; 


    public Test() 
    { 
        this.innerTest = new InnerTest(); 
        this.testNumber = 5; 
    } 


    public int TestNumber1 
    { 
        get { return this.testNumber; } 
        set { this.testNumber = value;} 
    } 


    public InnerTest InnerTest 
    { 
        get { return this.innerTest; } 
        set { this.innerTest = value;} 
    } 


} 


public struct InnerTest 
{ 
    private int number; 


    public InnerTest(int number) 
    { 
        this.number = number; 
    } 
    public int Number{get { return number; }} 
} 
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
6 089
4

Ответы 4

Сам я никогда этого не делал, но подозреваю, что вам просто нужно реализовать интерфейс IXmlSerializable.

Насколько я могу судить, это означает, что вы имеют, чтобы сделать свою структуру изменяемой, что является проблемой. В идеале XmlSerializer должен распознавать, есть ли у вашего типа конструктор с определенной сигнатурой, но, поскольку это не вариант (насколько я понимаю), стоило бы реализовать интерфейс с использованием явной реализации интерфейса, чтобы хотя бы препятствовать пользователи не могут использовать его напрямую.

Интересно, как управляются другие структуры (например, DateTime) ... возможно, они имеют явную поддержку в XmlSerializer.

Привет, Джон, к сведению, у меня была такая же проблема (на самом деле у меня было довольно много), поэтому я просмотрел справочный источник XmlSerializer, и на самом деле объект DateTime обрабатывается особым образом.

Michael Graczyk 16.05.2012 04:10

Класс XmlSerializer сериализует типы на основе System.TypeCode, возвращаемого методом Type.GetTypeCode (). Для DateTimes используется метод Convert.ToDateTime (String). К сожалению, все определяемые пользователем структуры обрабатываются как TypeCode.Object с целью сериализации с помощью XmlSerializer.

Michael Graczyk 16.05.2012 04:16

Как совершенно правильно говорит Джон Скит, вам нужно будет использовать IXmlSerializable с XmlSerializer, если вы не хотите иметь общедоступное получение / установку свойств, потому что оно предназначено для работы в среде с частичным доверием, поэтому не будет доступа ни к одному из них. данные, к которым вы все равно не могли получить доступ (чтобы ответить на его последнюю часть - да, некоторые структуры, такие как DateTime, действительно имеют явную поддержку в этом сериализаторе).

В зависимости от того, чего вы пытаетесь достичь и какую версию .NET вы используете, вы можете рассмотреть возможность использования DataContractSerializer, который не требует, чтобы что-то было общедоступным (например, вы можете поместить DataMemberAttribute в частное поле или свойство с публичным геттером и частным сеттером). Этот сериализатор дает вам меньше контроля над форматом XML (на самом деле он очень ограничен - например, он даже не поддерживает атрибуты!), Но несколько быстрее, чем окупаемость.

(Я давно мечтал о чем-то, что представляет собой комбинацию этих двух, то есть гибкости XmlSerializer с возможностью сериализации частных членов, таких как DataContractSerializer, но, к сожалению, на данный момент их нет.)

Если возможно в этом сценарии, я бы использовал DataContractSerializer (.NET 3.0), и я бы использовал что-то вроде:

[DataMember]
public int TestNumber1 
{ 
    get { return this.testNumber; } 
    set { this.testNumber = value;} 
} 

// note **not** a data-member
public InnerTest InnerTest 
{ 
    get { return this.innerTest; } 
    set { this.innerTest = value;} 
} 

[DataMember]
private int InnerTestValue
{
    get {return innerTest.Number;}
    set {innerTest = new InnerTest(value);}
}

таким образом обойдя проблему. Вы можете сделать то же самое с XmlSerializer, но вам нужно сделать InnerTestValue общедоступным (хотя вы можете украсить его [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)], но это не идеально).

Конечно, если у вас есть несколько значений в структуре ... сложнее. Конечно, у вас может быть несколько свойств прокладки, но это немного неаккуратно. По сути, [де] сериализация и неизменяемые объекты (как и должны быть структуры) не очень хорошо сочетаются.

Другой вариант - поддерживать отдельную версию POCO, которая использует изменяемые классы повсюду, и переводить между ними; опять же, не очень привлекательный вариант для моделей больших объектов.

Вы определенно можете использовать XmlSerializer на своем объекте и получить ожидаемый результат:

Test test = new Test { TestNumber1 = 5 };

XmlSerializer xmlSer = new XmlSerializer(typeof(Test));
MemoryStream memStm = new MemoryStream();

xmlSer.Serialize(memStm, test);

Чтобы проверить результат, снова считайте поток памяти в строку и посмотрите его в отладчике (или запишите в файл):

StreamReader stmR = new StreamReader(memStm);
memStm.Position = 0;
string output = stmR.ReadToEnd();

Если вы не сделаете ничего особенного, все общедоступные свойства класса, который вы сериализуете, будут отображаться как элементы XML ... в полученном XML.

Существует множество атрибутов, таких как [XmlIgnore] и многие другие, которые можно настроить по мере необходимости.

Наслаждаться!

Другие вопросы по теме