如何根据WCF中的内容自定义数据序列化? [英] How to customize data serialization based on content in WCF?

查看:28
本文介绍了如何根据WCF中的内容自定义数据序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试序列化类似联合的数据类型.有一个 enum 字段指示联合中存储的数据类型,以及多种可能的字段类型.

Trying to serialize a union-like data-type. There is an enum field indicating the type of data stored in the union, and a variety of possible field types.

所需的结果是 DataContractSerializer 生成的 XML,其中仅包含枚举和相关字段.

The desired result is DataContractSerializer produced XML which contains just the enum, and the relevant field.

尚未尝试过的可能解决方案是:

Possible solutions, none of which have been attempted yet, are:

  • 使用自定义序列化程序并使用自定义属性标记联合属性,类似于 this问题.自定义序列化程序会去掉不需要的成员.
  • 使用 ISerializationSurrogate 并序列化一个只包含相关数据的不同对象.
  • 不要在联合中使用单独的字段,使用一个对象字段(这可以用作 ISerializationSurrogate 方法.
  • 其他……?
  • Use a custom serializer and mark the union properties with a custom attribute, similar to this question. The custom serializer would strip out the members not required.
  • Use ISerializationSurrogate and serialize a different object which just contains the relevant data.
  • Don't use separate fields in the union, use one object field (this could be used as part of the implementation of the ISerializationSurrogate approach).
  • Other... ?

例如:

[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>

所需的输出(仅使用的字段与枚举一起序列化):

Desired Output (only field being used is serialized, along with 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>

推荐答案

这里有几个选项.你使用什么取决于这个场景的复杂性(你还有什么地方需要做这样的事情,你必须以何种频率和方式序列化这些数据,性能等)看看这些选项,问问你是否有更多问题,但大多数情况下,我建议您在选择一种或混合解决方案之前,先尝试并尝试以下列表中的多种策略.

You do have several options here. What you use depends on the complexity of this scenario (where else you have to do something like this, how often and in what ways you have to serialize this data, performance, etc.) Take a look at these options, ask away if you have more questions, but mostly, I recommend you just play and experiment with multiple strategies from the list below before picking one or a hybrid solution.

  • 使用数据合同解析器.提供一种机制,用于在序列化和反序列化期间动态地将类型映射到线表示和从线表示映射,从而使您能够灵活地支持远多于开箱即用的类型.

  • Use a data contract resolver. Provides a mechanism for dynamically mapping types to and from wire representations during serialization and deserialization, giving you flexibility to support far more types than you can out-of-the-box.

使用 IObjectReference.您可以拥有一个类,该类在反序列化后实现并返回对不同对象的引用.

Use IObjectReference. You can have a class which implements and returns a reference to a different object after it has been deserialized.

使用数据合同代理.这与您所指的序列化代理不同,但也相似.我认为这些可能对你很有效

Use a data contract surrogate. This is different from the serialization surrogates you're referring to, but also similar. I think these might work out nicely for you

这篇关于如何根据WCF中的内容自定义数据序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆