Почему у SerializationInfo нет методов TryGetValue?
При реализации интерфейса ISerializable
в С# мы предоставляем конструктор, который принимает объект SerializationInfo
, а затем запрашивает его с помощью различных методов GetInt32
, GetObject
и т.д., чтобы заполнить поля объекта которые мы пытаемся десериализовать.
Одна из основных причин реализации этого интерфейса, а не просто использование атрибута [Serializable]
, заключается в обратной совместимости: если в какой-то момент мы добавили новые классы в класс, мы сможем поймать SerializationException
, созданный сериализованным, более старую версию класса и обрабатывать их соответствующим образом.
Мой вопрос заключается в следующем: почему мы должны использовать эти исключения для того, что, по сути, управляет потоком? Если я десериализую большое количество классов, которые были сохранены некоторое время назад, потенциально каждое отсутствующее поле в каждом классе генерирует исключение, что вызывает очень плохую производительность.
Почему класс SerializationInfo
не предоставляет методы TryGetValue
, которые просто возвращают false
, если строка имени не присутствовала?
Ответы
Ответ 1
Вы можете перебирать доступные поля и использовать switch
, хотя...
foreach(SerializationEntry entry in info) {
switch(entry.Name) {
...
}
}
Или вы можете использовать protobuf-net;-p
Ответ 2
Ну, никто не ответил "почему", но я предполагаю, что это адресовано MS.
Моя реализация для любого, кто в ней нуждается:
public static class SerializationInfoExtensions
{
public static bool TryGetValue<T>(this SerializationInfo serializationInfo, string name, out T value)
{
try
{
value = (T) serializationInfo.GetValue(name, typeof(T));
return true;
}
catch (SerializationException)
{
value = default(T);
return false;
}
}
public static T GetValueOrDefault<T>(this SerializationInfo serializationInfo, string name, Lazy<T> defaultValue)
{
try
{
return (T) serializationInfo.GetValue(name, typeof(T));
}
catch (SerializationException)
{
return defaultValue.Value;
}
}
}