Если GetData
возвращает IList
, измените e.Data.GetData(DataFormats.FileDrop)(0)
на e.Data.GetData(DataFormats.FileDrop)[0]
XmlSerializer поддерживает шаблон ShouldSerialize{Foo}()
, поэтому вы можете добавить метод:
public bool ShouldSerializeID() {return ID.HasValue;}
Существует также шаблон {Foo}Specified
- не уверен, поддерживает ли XmlSerializer этот.
Я использую этот микро-шаблон для реализации Nullable serialization:
[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; } }
Это обеспечивает правильный интерфейс для пользователя без компромиссов и по-прежнему делает правильную вещь при сериализации.
Очень полезная публикация очень помогла.
Я решил перейти с версией Скотта к типу данных 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) Specified pattern, поскольку для этого требуется добавить к моим объектам нагрузки избыточных избыточных свойств, тогда как использование нового типа Nullable требует повторного набора свойств.
Я выяснил обходное решение, использующее два свойства. 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 сердце 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 & lt; int & gt;), но кроме этого все поведение остается неизменным.
System.ExecutionEngineException
на XmlSerializer.Serialize
.
– modiX
9 May 2014 в 08:41
К сожалению, описанные вами поведения точно документированы как таковые в документах для XmlElementAttribute.IsNullable.
HasValue
в свойстве. – Steven Sudit 16 August 2010 в 19:06Foo
у вас также естьpublic bool FooSpecified {get {...} set {...}}
, тоget
используется, чтобы видеть, следует ли сериализоватьFoo
, и вызываетсяset
при назначении значения доFoo
во время десериализации. – Marc Gravell♦ 20 September 2011 в 11:25