.NET, почему я должен использовать * указанное свойство для принудительной сериализации? Есть ли способ этого не делать? - PullRequest
17 голосов
/ 15 июля 2011

Я использую сериализацию xml в своем проекте для сериализации и десериализации объектов на основе схемы xml.Я использовал инструмент xsd для создания классов, которые будут использоваться при сериализации / десериализации объектов.

Когда я иду к сериализации объекта перед отправкой, я вынужден установить для свойства * Specified значение true, чтобы заставить сериализатор сериализовать все свойства, отличные от типа string.

Есть ли способ заставить сериализовать все свойства, не устанавливая свойство * Specified в true?

Ответы [ 5 ]

21 голосов
/ 18 июля 2011

Свойство FooSpecified используется для контроля необходимости сериализации свойства Foo.Если вы всегда хотите сериализовать свойство, просто удалите свойство FooSpecified.

5 голосов
/ 17 марта 2016

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

Простой способ получить то, что я действительно хотел и все еще использовал xsd.exe, - запустить созданный файл через простой постпроцессор.Код для постпроцессора выглядит следующим образом:

namespace XsdAutoSpecify
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            if (args.Length != 1)
            {
                throw new ArgumentException("Specify a file name");
            }

            string fileName = args[0];
            Regex regex = new Regex(".*private bool (?<fieldName>.*)Specified;");

            IList<string> result = new List<string>();
            IDictionary<string, string> edits = new Dictionary<string, string>();

            foreach (string line in File.ReadLines(fileName))
            {
                result.Add(line);
                if (line.Contains("public partial class"))
                {
                    // Don't pollute other classes which may contain like-named fields
                    edits.Clear();
                }
                else if (regex.IsMatch(line))
                {
                    // We found a "private bool fooSpecified;" line.  Add
                    // an entry to our edit dictionary.
                    string fieldName = regex.Match(line).Groups["fieldName"].Value;
                    string lineToAppend = string.Format("this.{0} = value;", fieldName);
                    string newLine = string.Format("                this.{0}Specified = true;", fieldName);
                    edits[lineToAppend] = newLine;
                }
                else if (edits.ContainsKey(line.Trim()))
                {
                    // Use our edit dictionary to add an autospecifier to the foo setter, as follows:
                    //   set {
                    //       this.fooField = value;
                    //       this.fooFieldSpecified = true;
                    //   }
                    result.Add(edits[line.Trim()]);
                }
            }

            // Overwrite the result
            File.WriteAllLines(fileName, result);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Environment.Exit(-1);
        }
    }
}
}

В результате генерируется код, подобный следующему:

    [System.Xml.Serialization.XmlAttributeAttribute()]
    public barEnum foo {
        get {
            return this.fooField;
        }
        set {
            this.fooField = value;
            this.fooFieldSpecified = true;
        }
    }
2 голосов
/ 08 февраля 2019

Я столкнулся с той же проблемой и закончил тем, что установил все * Указанные свойства в true путем отражения.

Как

var customer = new Customer();
foreach (var propertyInfo in typeof(Customer).GetProperties().Where(p => p.Name.EndsWith("Specified")))
{
    propertyInfo.SetValue(customer, true);
}
1 голос
/ 03 августа 2011

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

1 голос
/ 16 июля 2011

Вы можете добавить значение по умолчанию к вашей схеме и затем использовать DefaultValueAttribute .

Например, в вашей схеме может быть следующее:

<xs:element name="color" type="xs:string" default="red"/>

А потом следующее свойство для сериализации:

[DefaultValue(red)]
public string color { get; set; }

Это должно заставить свойство color всегда сериализоваться как «красное», если оно не было явно установлено для чего-то другого.

...