Я думаю, вам придется сериализовать его дважды, чтобы получить именно тот эффект, который вы описали. Одним из способов сделать это проще было бы не использовать XmlIgnore, а вместо этого добавить общедоступное указанное свойство (которое сериализация .NET XML обрабатывает специально для программного контроля, следует ли отправлять одноименное свойство):
[XmlIgnore]
public bool HmacSpecified
{
get { return !String.IsNullOrEmpty(this.Hmac); }
set { }
}
То, что это будет делать, это испускать hmac
узел XML, только если он существует. Подобный эффект может быть достигнут с DefaultValueAttribute
, но я обнаружил некоторые несоответствия с ним (например, null
иногда заменяется на ""
во время компиляции). Кроме того, если бы ваша логика была более сложной, чем одиночное постоянное значение, вы могли бы обрабатывать это в свойстве, но не в статическом атрибуте.
get { return !this.IsCalculatingHmac(); }
Я бы поступил так, если бы формат точно совпадал с тем, что вы описали.
Если у вас есть гибкость в формате вывода, другой подход, который вы могли бы рассмотреть, - это наличие контейнера сообщений, который содержит тело сообщения (ваш текущий документ XML) и значение подписи HMAC. Таким образом, вам нужно будет только сериализовать документ один раз.
Даже если конверт был частью большого сериализационного документа, вы могли бы реализовать интерфейс IXmlSerializable.WriteXml
на конверте. Это позволит вам аккуратно сериализовать сообщение в строку, затем выполнить хеш, а затем записать HMAC и элементы сообщения в одном через XmlWriter.WriteRaw
.
Так бы я поступил, если бы производительность была важна.