Pull to refresh

Comments 12

Double, int, bool — это типы значений (Value Types), и они не могут принимать значение null; в результате int свойства сериализуются значением по умолчанию (читай, если int свойству не присвоили значение, сериализуется 0).

Хм, а вы правда не знаете про minOccurs="0" и паттерн *Specified, или просто в статье не упомянули?
Знаю.
Но в данном случае они будут усложнять код DTO-класса.
Сравните:
[XmlElement]
public XmlDecimalWrapper NullableDecimal{get;set;}

и
[XmlElement]
public decimal NullableDecimal{get;set;}

[XmlIgnore]
public bool NullableDecimalSpecified{get{ AnyAdditionalLogicHere;}}


При наличии одного-двух полей — можно и IsSpecified использовать; плюс, этот способ приходится использовать с атрибутами.
При наличии же большого числа Value Type полей мне кажется более удобным использовать оберточные типы, особенно, если они уже есть в готовом виде.

Почему нельзя использовать nullable-тип из коробки, для которого даже есть красивый синтаксис (int? etc)?
Потому что XmlSerializer его не поддерживает.
Какой именно случай?
Сейчас запустил это
class Program
{
    static void Main(string[] args)
    {
        var xml1 = XDocument.Parse("<Test><Prop>5</Prop></Test>");
        var test1 = new XmlSerializer(typeof(Test)).Deserialize(xml1.CreateReader()) as Test;
        var xml2 = XDocument.Parse("<Test></Test>");
        var test2 = new XmlSerializer(typeof(Test)).Deserialize(xml2.CreateReader()) as Test;
        Console.WriteLine(test1.Prop.HasValue);
        Console.WriteLine(test2.Prop.HasValue);
    }
}

public class Test
{
    public int? Prop { get; set; }
}

Вывод:
true
false
Это у вас игра такая? Я же реально ответа не знал, потому и спросил…
Это сериализуется нормально
var test1 = new Test() { Prop = 5 };
var test2 = new Test();
var writer1 = new StringWriter();
var writer2 = new StringWriter();
new XmlSerializer(typeof(Test)).Serialize(writer1, test1);
new XmlSerializer(typeof(Test)).Serialize(writer2, test2);
Console.WriteLine(writer1.ToString());
Console.WriteLine(writer2.ToString());
Нормально — это как, с пропущенным тегом, или с xsi:nil? У меня просто сейчас нет возможности проверить.
witer1:
<?xml version="1.0" encoding="utf-16"?>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Prop>5</Prop>
</Test>

writer2:
<?xml version="1.0" encoding="utf-16"?>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Prop xsi:nil="true" />
</Test>
О, вот это поведение у нас и было. Вместо того, чтобы пропустить тег, как делается в случае со *Specified, он выводит xsi:nil.
К сожалению все эти Wrapper'ы не помогут сохранять примитивы в аттрибуты…
Да, с атрибутами приходится использовать *Specified, и красивого способа решить эту проблему я пока не вижу. Разве что, сниппет написать, или над когогенерирующей утилитой задуматься.

С перечислениями тоже неудобно работать. Писать обертку на каждый enum — раздувать проект, а удобную обобщенную оболочку вроде
public class EnumWrapper<T> where T : Enum

написать не получится.
Sign up to leave a comment.

Articles

Change theme settings