Страница: 1 |
Страница: 1 |
Вопрос: Десериализация и DefaultValueAttribute
Добавлено: 11.04.06 16:31
Автор вопроса: Comanche
Допустим, имею класс с двумя свойствами:
Public Property IntProp() As Integer
Get
IntProp = c_IntProp
End Get
Set(ByVal value As Integer)
c_IntProp = value
End Set
End Property
<DefaultValueAttribute("Вася")> _
Public Property StrProp() As String
Get
StrProp = c_StrProp
End Get
Set(ByVal value As String)
c_StrProp = value
End Set
End Property
Как видите, у каждого из свойств установлено дефолтное значение. Поэтому, когда я сериализую (через XmlSerializer и FileStream) экземпляр этого класса, то в итоговый XML-файл попадают только те свойства, значения которых отличаются от дефолтных. Например, если IntProp = 123 (не равно 5), а StrProp = "Вася" (совпадает с дефолтом), то XML будет выглядеть так:
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<IntProp>123</IntProp>
</TestClass>
т.е. StrProp в него не попадает. Что ж, так и задумано.
Однако, когда я выполняю десериализацию из этого XML-файла, то StrProp получит пустое значение, - если только в конструкторе класса нет явной инициализации свойства StrProp в строку "Вася". Получается, что дефолтные значения нужно указывать в ДВУХ местах: в атрибутах DefaultValueAttribute и в коде конструктора. С одной стороны, это логично: атрибуты - это метаданные, а конструктор - это код. Но с другой стороны, очень хоцца сказать конструктору: "А ну-ка возьми-ка начальные значения всех членов класса из метаданных! чтоб мне любимому дважды не писАть!"... вопрос в том, КАК это сделать? как заставить конструктор проинициализировать экземплярные члены класса значениями из соотв. атрибутов DefaultValueAttribute?!
Ответы
Всего ответов: 4
Номер ответа: 1
Автор ответа:
Comanche
Вопросов: 87
Ответов: 459
Профиль | | #1
Добавлено: 11.04.06 17:19
Хм... похоже, не я один этим вопросом задавался:
на странице http://support.microsoft.com/kb/311339/en-us сказано:
...
...
However, the DefaultValue attribute does not cause the initial value to be initialized with the attribute's value.
Иными словами, нужно явно задавать дефолты в ДВУХ местах - и в атрибуте, и в конструкторе. Вот так. Причём в конструкторе можно читать прямо из метаданных:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconretrievinginformationstoredinattributes.asp
(статья "Retrieving Information Stored in Attributes".
Сам спросил - сам ответил
Номер ответа: 2
Автор ответа:
vito
Разработчик Offline Client
Вопросов: 23
Ответов: 879
Web-сайт:
Профиль | | #2
Добавлено: 11.04.06 18:01
Не успел, ответить
Именно так, в двух местах.
Можно создать перегруженный конструктор для десериализации.
Public Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
Me.x = info.GetInt32("IntProp"
Me.y = info.GetString("StrProp"
'Dim d As Date = info.GetDateTime("TimeStamp"
End Sub
Номер ответа: 3
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #3
Добавлено: 11.04.06 21:58
Я тоже задавался этой проблемой, но так же ничего не вышло.. Чтобы обойти это, я иницилизирую переменную при объявлении, а не в конструкторе. Хотя, в общем-то, разницы никакой..
Номер ответа: 4
Автор ответа:
Comanche
Вопросов: 87
Ответов: 459
Профиль | | #4
Добавлено: 11.04.06 23:39
2vito:
Только вот есть щас задумка инициализировать свойства с их перебором в цикле и с авто-определением типов у каждого, чтобы в конструкторе явно не перечислять все свойства одно за другим и не писАть, где GetInt32, а где GetString.