Как настроить сериализацию данных на основе контента в WCF? - PullRequest
1 голос
/ 20 марта 2012

Попытка сериализовать объединенный тип данных.Существует поле перечисления, указывающее тип данных, хранящихся в объединении, и множество возможных типов полей.

Желаемый результат - DataContractSerializer созданный XML, который содержит только перечисление и соответствующее поле.

Возможные решения, ни одно из которых еще не было предпринято:

  • Использование настраиваемого сериализатора и пометка свойств объединения с помощью пользовательского атрибута, аналогичного этому вопросу .Пользовательский сериализатор удалит ненужные элементы.
  • Используйте ISerializationSurrogate и сериализуйте другой объект, который просто содержит соответствующие данные.
  • Не используйте отдельные поля в объединении, используйте одно поле объекта (это может бытьиспользуется как часть реализации подхода ISerializationSurrogate ).
  • Другое ...?

Например:

[DataContract]
public class WCFTestUnion
{
    public enum EUnionType
    {
        [EnumMember]
        Bool,
        [EnumMember]
        String,
        [EnumMember]
        Dictionary,
        [EnumMember]
        Invalid
    };

    EUnionType unionType = EUnionType.Invalid;

    bool boolValue = true;
    string stringValue = "Hello";
    IDictionary<object, object> dictionaryValue = null;

    // Could use custom attribute here ?
    [DataMember]
    public bool BoolValue
    {
        get { return this.boolValue; }
        set { this.boolValue = value; }
    }

    // Could use custom attribute here ?
    [DataMember]
    public string StringValue
    {
        get { return this.stringValue; }
        set { this.stringValue = value; }
    }

    // Could use custom attribute here ?
    [DataMember]
    public IDictionary<object, object> DictionaryValue
    {
        get { return this.dictionaryValue; }
        set { this.dictionaryValue = value; }
    }

    [DataMember]
    public EUnionType UnionType
    {
        get { return this.unionType; }
        set { this.unionType = value; }
    }
} // Ends class WCFTestUnion

Тест

    class TestSerializeUnion
    {
        internal static void Test()
        {
            Console.WriteLine("===TestSerializeUnion.Test()===");

            WCFTestUnion u = new WCFTestUnion();
            u.UnionType = WCFTestUnion.EUnionType.Dictionary;
            u.DictionaryValue = new Dictionary<object, object>();
            u.DictionaryValue[1] = "one";
            u.DictionaryValue["two"] = 2;

            System.Runtime.Serialization.DataContractSerializer serialize = new System.Runtime.Serialization.DataContractSerializer(typeof(WCFTestUnion));
            System.IO.Stream stream = new System.IO.MemoryStream();

            serialize.WriteObject(stream, u);

            stream.Seek(0, System.IO.SeekOrigin.Begin);
            byte[] buffer = new byte[stream.Length];
            int length = checked((int)stream.Length);
            int read = stream.Read(buffer, 0, length);
            while (read < stream.Length)
            {
                read += stream.Read(buffer, 0, length - read);
            }

            string xml = Encoding.Default.GetString(buffer);

            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            doc.LoadXml(xml);

            System.Xml.XmlTextWriter xmlwriter = new System.Xml.XmlTextWriter(Console.Out);
            xmlwriter.Formatting = System.Xml.Formatting.Indented;

            doc.WriteContentTo(xmlwriter);
            xmlwriter.Flush();

            Console.WriteLine();
        }
    } // Ends class TestSerializeUnion

Выход:

<WCFTestUnion xmlns="http://schemas.datacontract.org/2004/07/WCFTestServiceContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <BoolValue>true</BoolValue>
  <DictionaryValue xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <a:KeyValueOfanyTypeanyType>
      <a:Key i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:Key>
      <a:Value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">one</a:Value>
    </a:KeyValueOfanyTypeanyType>
    <a:KeyValueOfanyTypeanyType>
      <a:Key i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">two</a:Key>
      <a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">2</a:Value>
    </a:KeyValueOfanyTypeanyType>
  </DictionaryValue>
  <StringValue>Hello </StringValue>
  <UnionType>Dictionary</UnionType>
</WCFTestUnion>

Требуемый выход (сериализуется только используемое поле вместе с enum):

<WCFTestUnion xmlns="http://schemas.datacontract.org/2004/07/WCFTestServiceContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <DictionaryValue xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <a:KeyValueOfanyTypeanyType>
      <a:Key i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:Key>
      <a:Value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">one</a:Value>
    </a:KeyValueOfanyTypeanyType>
    <a:KeyValueOfanyTypeanyType>
      <a:Key i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">two</a:Key>
      <a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">2</a:Value>
    </a:KeyValueOfanyTypeanyType>
  </DictionaryValue>
  <UnionType>Dictionary</UnionType>
</WCFTestUnion>

1 Ответ

2 голосов
/ 26 апреля 2012

У вас есть несколько вариантов здесь.То, что вы используете, зависит от сложности этого сценария (где еще вы должны сделать что-то подобное, как часто и каким образом вам нужно сериализовать эти данные, производительность и т. Д.) Посмотрите на эти варианты, спросите, если выУ меня есть еще вопросы, но в основном я рекомендую вам просто поиграть и поэкспериментировать с несколькими стратегиями из списка ниже, прежде чем выбирать одно или гибридное решение.

  • Использовать средство разрешения контрактов данных .Предоставляет механизм для динамического отображения типов в и из представлений проводов во время сериализации и десериализации, предоставляя вам гибкость для поддержки гораздо большего количества типов, чем вы можете из коробки.

  • Используйте IObjectReference .У вас может быть класс, который реализует и возвращает ссылку на другой объект после его десериализации.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...