【问题标题】:Can I prevent a specific datamember from being deserialized?我可以防止特定数据成员被反序列化吗?
【发布时间】:2010-07-29 00:10:51
【问题描述】:

我有这样的数据合同

[DataContract]
class MyDC 
{
    [DataMember]
    public string DM1;

    [DataMember]
    public string DM2;

    [DataMember]
    public string DM3;
}

并且有时我想防止 DM2 在从 OperationContract 返回时被反序列化。像这样的:

[OperationContact]
public MyDC GetMyDC()
{
    MyDC mdc = new MyDC();

    if (condition)
    {
        // Code to prevent DM2 from being deserialized  
    }

    return mdc;
}

我总是可以创建一个只有 DM1 和 DM3 的新 DataContract 并从 MyDC 实例生成它,但我想看看是否可以以编程方式删除 DM2。可能吗?怎么样?

【问题讨论】:

    标签: wcf serialization datacontract datamember


    【解决方案1】:

    一种方法是将 DataMemberAttribute 的 EmitDefaultValue 属性设置为 false:

    [DataContract]
    class MyDC 
    {
        [DataMember]
        public string DM1;
    
        [DataMember(EmitDefaultValue = false)]
        public string DM2;
    
        [DataMember]
        public string DM3;
    }
    

    然后将此属性设置为null:

    [OperationContact]
    public MyDC GetMyDC()
    {
        MyDC mdc = new MyDC();
    
        if (condition)
        {
            // Code to prevent DM2 from being deserialized  
            mdc.DM2 = null;
        }
    
        return mdc;
    }
    

    这样,该属性不会在序列化时写入输出流。

    http://msdn.microsoft.com/en-us/library/aa347792.aspx

    【讨论】:

    • 如果我正在创建我想要序列化的实际对象的副本,并且不关心更改副本,那么这很有效。但是,我想在不更改我尝试序列化的对象的情况下这样做。
    【解决方案2】:

    你的意思是序列化而不是反序列化。

    如果您准备一个用于序列化的类,将[DataContract] 属性应用于该类,则只有具有[DataMember] 属性的类的成员将被序列化:

    [DataContract]
    class MyDC 
    {
        [DataMember]
        public string DM1;
    
        public string DM2;
    
        [DataMember]
        public string DM3;
    }
    

    在一些更复杂的情况下,[IgnoreDataMember] 的使用可以解决您的问题。 (见http://msdn.microsoft.com/en-us/library/ms733127.aspx

    顺便说一句,无论可访问性如何,您都可以序列化字段和属性:privateprotectedinternalprotected internalpublic。您可以序列化任何读/写属性,而不仅仅是字段。关于集合类型的序列化参见http://msdn.microsoft.com/en-us/library/aa347850.aspx

    【讨论】:

      【解决方案3】:
      [DataContract]
      class MyDC 
      {
          [DataMember]
          public string DM1;
      
          public string DM2;
      
          public bool IsDM2Serializable;
      
          [DataMember(Name="DM2", EmitDefaultValue = false)]
          public string DM2SerializedConditionally
          {
              get
              {
                  if(IsDM2Serializable)
                      return null;
                  return DM2;
              }
              set { DM2=value; }
          }
      
          [DataMember]
          public string DM3;
      }
      

      然后在需要隐藏的时候设置 IsDM2Serializable 为 false:

      [OperationContact]
      public MyDC GetMyDC()
      {
          MyDC mdc = new MyDC();
      
          if (condition)
          {
              // Code to prevent DM2 from being serialized  
              mdc.IsDM2Serializable = false;
          }
      
          return mdc;
      }
      

      【讨论】:

        【解决方案4】:

        是的,我们可以防止属性序列化。 将[DataContract] 注释放在类上,[DataMember] 仅用于序列化属性。如果您想在该属性值为 null 时跳过该属性,则将 [DataMember(EmitDefaultValue = false)] 放在该属性上。

        例子:

        [DataContract]
        public class MyClass 
        {
            [DataMember]
            public int Id{ get; set; } 
            [DataMember]
            public string Title { get; set; }
            [DataMember]
            public string MessageBody { get; set; }
        
            [DataMember(EmitDefaultValue = false)]
            public DateTime SentOn { get; set; } 
        }
        

        注意:当不为空时,SentOn 将被序列化,而其他任何情况下都会被序列化。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-11
          • 2018-06-21
          • 2023-04-07
          相关资源
          最近更新 更多