Сериализовать nullable int
у меня есть класс с nullable int? тип данных, заданный для сериализации в виде xml-элемента. Есть ли способ настроить его так, чтобы XML-сериализатор не сериализовал элемент, если значение равно null?
Я попытался добавить [System.XML.Сериализация.Xmlelement (IsNullable=false)] атрибут, но я получаю исключение сериализации во время выполнения говоря, что была ошибка, отражающая тип, потому что "IsNullable не может быть установлен в "false" для типа Nullable. Рассмотрите возможность использования 'System. Int32' введите или удалите свойство IsNullable из атрибута XmlElement."
[Serializable]
[System.Xml.Serialization.XmlRoot("Score", Namespace = "http://mycomp.com/test/score/v1")]
public class Score
{
private int? iID_m;
...
/// <summary>
///
/// </summary>
public int? ID
{
get
{
return iID_m;
}
set
{
iID_m = value;
}
}
...
}
вышеуказанный класс будет сериализован в:
<Score xmlns="http://mycomp.com/test/score/v1">
<ID xsi:nil="true" />
</Score>
но для идентификаторов, которые являются null я не хочу элемент ID вообще, в первую очередь потому, что когда я использую OPENXML в MSSQL, он возвращает 0 вместо null для элемента, который выглядит как
6 ответов:
XmlSerializer поддерживает
ShouldSerialize{Foo}()
шаблон, так что вы можете добавить метод:public bool ShouldSerializeID() {return ID.HasValue;}
есть еще
{Foo}Specified
pattern-не уверен, что XmlSerializer поддерживает это.
Я использую этот микро-шаблон для выполнения сериализации значение null:
[XmlIgnore] public double? SomeValue { get; set; } [XmlAttribute("SomeValue")] // or [XmlElement("SomeValue")] [EditorBrowsable(EditorBrowsableState.Never)] public double XmlSomeValue { get { return SomeValue.Value; } set { SomeValue= value; } } [EditorBrowsable(EditorBrowsableState.Never)] public bool XmlSomeValueSpecified { get { return SomeValue.HasValue; } }
Это обеспечивает правильный интерфейс для пользователя без компромиссов и по-прежнему делает правильные вещи при сериализации.
Я придумал обходной путь, используя два свойства. Тип int? свойство с атрибутом XmlIgnore и свойством объекта, которое сериализуется.
/// <summary> /// Score db record /// </summary> [System.Xml.Serialization.XmlIgnore()] public int? ID { get { return iID_m; } set { iID_m = value; } } /// <summary> /// Score db record /// </summary> [System.Xml.Serialization.XmlElement("ID",IsNullable = false)] public object IDValue { get { return ID; } set { if (value == null) { ID = null; } else if (value is int || value is int?) { ID = (int)value; } else { ID = int.Parse(value.ToString()); } } }
Вау Спасибо этот вопрос / ответ действительно помог мне. I heart Stackoverflow.
Я сделал то, что вы делаете выше немного более общий. Все, что мы действительно ищем, это иметь Nullable с немного другим поведением сериализации. Я использовал Reflector для создания своего собственного Nullable и добавил несколько вещей здесь и там, чтобы сделать сериализацию XML так, как мы хотим. Кажется, работает довольно хорошо:
public class Nullable<T> { public Nullable(T value) { _value = value; _hasValue = true; } public Nullable() { _hasValue = false; } [XmlText] public T Value { get { if (!HasValue) throw new InvalidOperationException(); return _value; } set { _value = value; _hasValue = true; } } [XmlIgnore] public bool HasValue { get { return _hasValue; } } public T GetValueOrDefault() { return _value; } public T GetValueOrDefault(T i_defaultValue) { return HasValue ? _value : i_defaultValue; } public static explicit operator T(Nullable<T> i_value) { return i_value.Value; } public static implicit operator Nullable<T>(T i_value) { return new Nullable<T>(i_value); } public override bool Equals(object i_other) { if (!HasValue) return (i_other == null); if (i_other == null) return false; return _value.Equals(i_other); } public override int GetHashCode() { if (!HasValue) return 0; return _value.GetHashCode(); } public override string ToString() { if (!HasValue) return ""; return _value.ToString(); } bool _hasValue; T _value; }
вы теряете возможность иметь своих членов как int? и так что (вместо этого нужно использовать Nullable
), но кроме этого все поведение остается прежним.
к сожалению, поведение, которое вы описываете, точно документировано как таковое в docs for XmlElementAttribute.Свойство isnullable.
очень полезное сообщение очень помогло.
Я решил пойти с ревизией Скотта к типу данных Nullable(of T), однако опубликованный код все еще сериализует элемент Nullable, когда он равен Null - хотя и без атрибута "xs:nil='true'".
Мне нужно было заставить сериализатор полностью удалить тег, поэтому я просто реализовал IXmlSerializable на структуре (это в VB, но вы получаете изображение):
'---------------------------------------------------------------------------- ' GetSchema '---------------------------------------------------------------------------- Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema Return Nothing End Function '---------------------------------------------------------------------------- ' ReadXml '---------------------------------------------------------------------------- Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml If (Not reader.IsEmptyElement) Then If (reader.Read AndAlso reader.NodeType = System.Xml.XmlNodeType.Text) Then Me._value = reader.ReadContentAs(GetType(T), Nothing) End If End If End Sub '---------------------------------------------------------------------------- ' WriteXml '---------------------------------------------------------------------------- Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml If (_hasValue) Then writer.WriteValue(Me.Value) End If End Sub
Я предпочитаю этот метод с помощью (foo)указанный шаблон, как это требует добавления ведро нагрузок избыточных свойств для моих объектов, в то время как использование нового типа Nullable просто требует перепечатки свойств.