Сериализация объекта без информации об объекте

Я нахожусь в ситуации, когда мне нужно сериализовать только значения членов объекта в файл.

например, если объект содержит 3 строковых члена, я бы хотел, чтобы на выходе сериализации были только эти 3 строки без метаданных сериализации, которые добавляет Binaryformatter, таких как версия, культура и имя сборки объект.

Один из вариантов — просто написать каждый член объекта напрямую, но я хочу избежать этого, потому что у меня есть много классов, которые нужно сериализовать таким образом, и я не хочу писать функцию, которая обрабатывает это по-разному для каждого класса.

Требования:

Я хочу иметь возможность писать в файл любого типа, я хочу, чтобы значения элементов были переведены в байты (в буфер или непосредственно в файл) и иметь возможность записывать эти байты в определенную позицию в файле. .

Есть ли способ или API для сериализации только значения членов объекта?


person Matan Givoni    schedule 04.02.2013    source источник
comment
Собираетесь ли вы когда-нибудь его десериализовать?   -  person Chris Sinclair    schedule 04.02.2013
comment
Вероятно, нет, но если я окажусь в ситуации, когда мне нужно будет десериализовать элементы объекта, я, вероятно, буду читать каждый член по отдельности.   -  person Matan Givoni    schedule 04.02.2013
comment
Существует множество альтернативных API сериализации; xml, json, protobuf и т. д. Все они могут использоваться без информации о метаданных типа. Но здесь отсутствует много требований/контекста...   -  person Marc Gravell    schedule 04.02.2013
comment
@Matan - Используя отражение, вы можете опросить объект, а затем записать нужные данные из объекта в файл. Это было бы обобщенно (вам нужно было бы написать его только один раз), и вы могли бы записать файл в нужном вам формате (по сравнению с использованием существующих API-интерфейсов сериализации). Ссылка на документацию Microsoft по отражению — › msdn.microsoft. com/en-us/library/ms173183(v=vs.80).aspx   -  person David Hope    schedule 05.02.2013
comment
@DavidHope +1 за использование отражения для опроса объекта.   -  person Chris Sinclair    schedule 05.02.2013
comment
@Matan: одно из ваших требований - иметь возможность писать в файлы любого типа ... это довольно широко.   -  person Chris Sinclair    schedule 05.02.2013
comment
Я хотел сказать, что смогу открыть файл, например, с помощью FileStream и сериализовать в этот поток.   -  person Matan Givoni    schedule 05.02.2013


Ответы (2)


Матан,

Вот некоторый код, который я собрал для совершенно другой цели, но он берет неизвестный объект и сериализует его в файл XML (обновленный, чтобы включить лучшие методы кодирования).

    void objectToXMLFile(String fn, object o)
    {
        XmlTextWriter textWriter = new XmlTextWriter(fn, null);

        System.Type type = o.GetType();
        PropertyInfo[] piList = type.GetProperties();

        textWriter.WriteStartDocument();

        textWriter.WriteStartElement("attributeList");

        foreach (PropertyInfo pi in piList)
        {
            textWriter.WriteStartElement("attribute");

            textWriter.WriteStartElement("name");
            textWriter.WriteString(pi.Name);
            textWriter.WriteEndElement();

            textWriter.WriteStartElement("value");
            textWriter.WriteString(pi.GetValue(o).ToString());
            textWriter.WriteEndElement();

            textWriter.WriteStartElement("dataType");
            textWriter.WriteString(pi.PropertyType.Name);
            textWriter.WriteEndElement();

            textWriter.WriteEndElement();
        }
        textWriter.WriteEndElement();
        textWriter.WriteEndDocument();
        textWriter.Close();
    }
person David Hope    schedule 04.02.2013
comment
В этом случае, не будет ли безопаснее использовать XmlSerializer с простой моделью данных AttributeList, поскольку она будет лучше обрабатывать особые случаи (например, значения, содержащие символы, требующие экранирования XML?) - person Chris Sinclair; 05.02.2013
comment
Для моего кода, да, это, вероятно, было бы лучшим способом действий. Однако код был представлен как пример использования отражения в C#, поэтому он по-прежнему актуален. - person David Hope; 05.02.2013
comment
Хорошо, я беру свои слова обратно, это отражение может работать для моего использования просто отлично. =] Я вообще не знал о существовании отражения. - person Matan Givoni; 05.02.2013
comment
к сожалению, это решение мне не подходит. Мои объекты имеют много типов членов, таких как int и string, и в конце мне нужно, чтобы члены были преобразованы в байты, отражение не дает мне лучшего решения, потому что теперь я потребуется преобразование байтов для каждого члена, и запись каждого объекта напрямую почти так же хороша. - person Matan Givoni; 05.02.2013
comment
Не могли бы вы использовать: ToString(), чтобы преобразовать его в строку, а затем написать строку? Согласен, это было бы пустой тратой места. - person David Hope; 05.02.2013
comment
Помимо требований, этот код будет иметь очень высокую стоимость производительности. @ Дэвид Хоуп, если вы настаиваете на самостоятельном форматировании XML и должны делать это в памяти (а не в файле), по крайней мере, используйте StringWriter или StringBuilder. Код, который вы написали, будет выделять массу строк - поскольку String неизменяем, каждый раз, когда вы используете +=, вы дублируете в памяти XML, который вы получили до сих пор. - person Ran; 05.02.2013
comment
@Ran - спасибо за совет. В данном случае я просто быстро что-то собирал и не продумывал. Я ценю, что ты позвонил мне. - person David Hope; 05.02.2013
comment
Я не могу использовать stringWriter, потому что не хочу писать число в кодировке ASCII. - person Matan Givoni; 05.02.2013

Если вы в конечном итоге используете Reflection только для записи нужных свойств, вы можете рассмотреть некоторые последствия для производительности.

Использование Reflection медленно. Отражение самого типа имеет высокую цену, а затем динамический вызов PropertyInfo путем вызова PropertyInfo.GetValue очень медленный.

Альтернативой является построение дерева выражений, которое вызывает свойства и записывает их значения, а затем компилирует это выражение в файл Action. Вы можете кэшировать эти экземпляры Action в словаре с ключом Type объекта, который вы сериализуете, и вызывать правильный экземпляр, когда хотите сериализовать объект.

Это было бы намного быстрее, а также не создавало бы такой большой нагрузки на сборщик мусора.

Другой альтернативой, которую вы можете рассмотреть, является генерация кода во время сборки — вы можете создать класс для сериализации вашего целевого типа быстро и дешево. В некоторых случаях это хороший выбор.

person Ran    schedule 04.02.2013
comment
Это не лучший вариант, моя проблема не в том, как хранить все свойства, а в том, как их сериализовать. - person Matan Givoni; 05.02.2013
comment
У меня есть много видов классов, функция, которая будет вызывать свойства и записывать их значения, будет реализована по-разному для каждого класса, и это то, чего я хочу избежать. Я ищу API, который будет записывать только значения свойств любого типа объекта. - person Matan Givoni; 05.02.2013
comment
@Matan, почему это должно быть реализовано по-другому? Вы можете написать 1 функцию, которая получает целевой тип для сериализации, просматривает свойства типа с помощью отражения и генерирует быстрое универсальное действие, которое может записывать свойства экземпляра этого типа. - person Ran; 06.02.2013