Можете ли вы контролировать глубину десериализации DataContractSerializer?

StackOverflow https://stackoverflow.com/questions/413349

Вопрос

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

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

Моя единственная идея сейчас - создать совместимое " резюме " объект, содержащий только те свойства, которые меня интересуют, и ни одного из дочерних, и десериализовать файл в него. Это должно пропустить детей, поскольку они не имеют отношения к объекту сводки.

Есть ли лучший способ сделать это?

Обновление / уточнение . Атрибуты - это не тот ответ, который я ищу. Во-первых, они предотвратят «дополнительные» операции. свойства попадают в файл при первой сериализации объекта.

Во-вторых, они более постоянны, чем то, что я пытаюсь сделать. В конце концов, я хочу десериализовать весь файл, но не сейчас. Я пытаюсь показать сводный список файлов, которые пользователь выберет для импорта. Во время импорта мне понадобятся все дети и внуки. Это просто избыточно на шаге 1. Это потенциально большие файлы, поэтому полная десериализация некоторых из них просто для того, чтобы я мог отобразить информацию их заголовков, не сработает.

Надеюсь, это устранит путаницу в исходном вопросе.

Это было полезно?

Решение

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

Учитывая это, просто создайте объект с подобным подмножеством свойств, которые вы хотите сериализовать, и передайте этот тип в DataContractSerializer.

Убедитесь, что в разделе "Сводка" введите, что вы задаете свойства атрибута DataContract (а также любые атрибуты DataMember или атрибуты DataContract для представляемых вами дочерних элементов), в частности свойства Name и Namespace, чтобы отражать имя и пространство имен не сводного типа (поскольку они должны совпадать) .

Другие советы

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

class Program
{
    static void Main(string[] args)
    {
        Person a = new Person();
        Person b = new Person();
        a.Name = "Mike";
        b.Name = "Joe";
        b.Parent = a;

        DataContractSerializer dtc = new DataContractSerializer(typeof(Person));

        StringBuilder sb = new StringBuilder();
        using (XmlWriter xr = XmlWriter.Create(sb))
        {
            dtc.WriteObject(xr, b);
        }

        object n;

        DataContractSerializer dtc2 = new DataContractSerializer(typeof(TinyPerson));

        using (XmlReader xr = XmlReader.Create(new StringReader(sb.ToString())))
        {
            n = dtc2.ReadObject(xr);
        }

    }
}

[DataContract(Name="Person")]
public class Person
{
    [DataMember]
    public string Name;

    [DataMember(IsRequired=false)]
    public Person Parent; 
}


[DataContract(Name = "Person")]
public class TinyPerson
{
    [DataMember]
    public string Name;

}

вы можете контролировать сериализацию с помощью атрибутов. Подробнее здесь

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top