Могу ли я сконфигурировать DataContractSerializer, чтобы не создавать необязательные (то есть Nullable <> и List <>) элементы в выходном XML?
Я использую новый .NET 3.0 DataContractSerializer. У меня есть объекты Nullable < > и List < > , которые я собираюсь сериализовать. Пример:
[DataContract(Namespace = "")]
class Test
{
public static void Go()
{
Test test = new Test();
var dcs = new DataContractSerializer(typeof(Test));
dcs.WriteObject(new StreamWriter("test.xml").BaseStream, test);
}
[DataMember]
public Nullable<int> NullableNumber = null;
[DataMember]
public int Number = 5;
[DataMember]
public List<int> Numbers = new List<int>();
}
Когда .NET сериализует нулевой или пустой список, он помещает nil (для Nullable) и пустые (для списков) элементы в XML. Вышеприведенный пример генерирует:
<Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<NullableNumber i:nil="true"/>
<Number>5</Number>
<Numbers xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
</Test>
По причинам у меня нет времени для описания, я хотел бы удалить лишние элементы NullableNumber и Numbers, например:
<Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Number>5</Number>
</Test>
В самом деле, этот файл десериализуется с помощью сериализатора просто отлично.
Спасибо за вашу помощь!
Ответы
Ответ 1
Отметьте поле с помощью
[DataMember(EmitDefaultValue=false)]
Это будет работать, по крайней мере, в случае типа nullable value type.
Для случая списка вам может потребоваться отложить создание списка до тех пор, пока он не понадобится, или иначе null, если он пуст до сериализации.
Ответ 2
Мне действительно нужно было то же самое, но было применено глобально к множеству полей в сгенерированных классах RIA. Я не уверен, является ли этот XML приемлемым для DataConstract для десериализации. Но он читабельен, и он подходит для моих целей...
public override string ToString()
{
var doc = XDocument.Parse(this.ToXML());
WalkElement(doc.Root);
return doc.ToString( SaveOptions.None );
}
void WalkElement(XElement e)
{
var n = e.GetNamespaceOfPrefix("i");
if (n != null)
{
var a = e.Attribute(n + "nil");
if (a != null && a.Value.ToLower() == "true")
e.Remove();
}
foreach (XElement child in e.Elements().ToList())
WalkElement(child);
}