Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 动态忽略序列化的数据成员_C#_.net_Wcf_Serialization - Fatal编程技术网

C# 动态忽略序列化的数据成员

C# 动态忽略序列化的数据成员,c#,.net,wcf,serialization,C#,.net,Wcf,Serialization,我们有一个现有的WCF服务,它使用多个DataContract。我们希望修改基于设备的序列化,这样当从移动设备访问时,服务应该只序列化一些重要的数据成员(不是全部) 我们有两个选择 为不同类型的数据创建单独的操作和数据契约 装置 干扰实际的xml序列化并禁止创建 基于设备的不必要元素 我们不想使用第一个选项,因为它在将来会引入很多冗余代码问题 小型研究表明,我们需要使用IXmlSerializable并重写readXML()和writeXML()方法。但同时,我发现DataContract和IX

我们有一个现有的WCF服务,它使用多个DataContract。我们希望修改基于设备的序列化,这样当从移动设备访问时,服务应该只序列化一些重要的数据成员(不是全部)

我们有两个选择

  • 为不同类型的数据创建单独的操作和数据契约 装置
  • 干扰实际的xml序列化并禁止创建 基于设备的不必要元素
  • 我们不想使用第一个选项,因为它在将来会引入很多冗余代码问题

    小型研究表明,我们需要使用IXmlSerializable并重写readXML()和writeXML()方法。但同时,我发现DataContract和IXmlSerializable不应该一起使用

    任何干扰实际序列化的示例都非常受欢迎

    [DataContract]
    public class TokenMessage
    {
        string tokenValue;
        string extraValue;
        [DataMember]
        public string Token
        {
            get { return tokenValue; }
            set { tokenValue = value; }
        }
        [DataMember]
        public string Extra 
        {
            get { return extraValue; }
            set { extraValue = value; }
        }
    }
    
    现在,当我从移动设备访问返回典型TokenMessage数据协定的服务时,我不希望“额外”数据成员被序列化,也就是说,当我为操作协定提供不同的参数时,它应该能够序列化部分/所有数据成员(取决于操作)


    PS:现在请忽略设备检测部分。假设我们在操作契约中有一个参数,它可以帮助我们识别模型中的设备。添加一个属性“shouldSerializedYour_property_NAME”,当您不想序列化该属性时,将其设置为false。
    请参阅此处的更多信息:

    尝试使用

    有一种方法,但我认为这将需要生成额外的DataContract,但仍然不需要为不同类型的设备单独操作和数据契约。 它可以实现运行时多态性。我只是想说:

    假设您有一个通用的DataContract,如:

    [DataContract]
    [KnownType(typeof(Extra))]
    [KnownType(typeof(Extra2))]
    public class TokenMessage
    {
        string tokenValue;
        string extraValue;
        [DataMember]
        public string Token
        {
            get { return tokenValue; }
            set { tokenValue = value; }
        }
    
    }
    
    其他特定于设备的契约可以将TokenMessage作为基类继承,如:

    [DataContract]
    public class Extra:TokenMessage
    {
      [DataMember]
      public string Extra 
      {
        get ;set;
      }
    }
    
    [DataContract]
    public class Extra2:TokenMessage
    {
      [DataMember]
      public string Extra2 
      {
        get ;set;
      }
    }
    
    TokenMessage tm= new Extra();
    
    现在在运行时,正如您所说,您知道操作合同中的一个参数,它帮助我们识别设备。假设基于设备类型,您可以使用派生类实例化基类,如:

    [DataContract]
    public class Extra:TokenMessage
    {
      [DataMember]
      public string Extra 
      {
        get ;set;
      }
    }
    
    [DataContract]
    public class Extra2:TokenMessage
    {
      [DataMember]
      public string Extra2 
      {
        get ;set;
      }
    }
    
    TokenMessage tm= new Extra();
    

    所以在运行时,您将决定哪个设备合同将成为genric响应的一部分


    注意:添加
    KnownType
    将在wsdl中为基类中的所有已知类型生成单独的xsd,但会在运行时保存数据的序列化,因为这应取决于实际选择的继承

    我不相信@Pranav Singh答案的某些变体不是更好的设计,但这不是你的问题

    正如您在注释中提到的那样,.NET中的属性在设计上是静态的。这意味着动态添加/删除
    [DataMember]
    不是一个好的选择。这是可能的。有一些选项,比如使用Reflection.Emit重新创建元数据更改的实例(请参阅所有答案),但所有这些路由都很复杂

    我认为有两个合理的选择:

    1) 为该服务实施一个。在()方法中,您可以在序列化之前检查并更改返回给客户机的参数。使用反射来动态确定参数类型并设置其值是有一些工作的,但并不复杂。这是一种更好的设计,可以跨多个契约或服务重用行为。是WCF扩展示例的最佳来源

    2) 使用和事件。在[DataContract]中,可以临时更改序列化期间返回的属性。这些事件实际上是为了启用初始化而设计的,因此这个解决方案有点像黑客。此解决方案也不是线程安全的。但它确实保留了DataContract类中包含的代码,并快速解决了问题(我认为您正在寻找快速解决方案)

    解决方案2可能类似于:

    [DataContract]
    public class TokenMessage
    {
        string tokenValue;
        string extraValue;
    
        bool enableExtraValue = true;
    
        [DataMember]
        public string Extra 
        {
            get { 
                    if (enableExtraValue) 
                          return extraValue;
                    return null; 
                }
            set { extraValue = value; }
        }
    
        [OnSerializing()]
        internal void OnSerializingMethod(StreamingContext context)
        {
            enableExtraValue = false;
        }
    
        [OnSerialized()]
        internal void OnSerializedMethod(StreamingContext context)
        {
            enableExtraValue = true;
        }
    }
    
    解决方案2是一个快速解决方案(我认为您正在寻找)


    解决方案#1是更好的设计。

    使用接口并返回接口而不是类。您的意思是“添加ShouldSerializeToken和ShouldSerializeExtra属性并将其设置为false?”WCF是否会自动检测到这一点?上述方法没有成功之处:(
    ShouldSerialize
    与WPF有关,我不知道这对您的WCF服务有什么帮助。将EmitDefaultValue设置为false并显式将属性设置为默认值是阻止数据成员序列化的一种方法。但是,我的类成员不仅仅是基本数据类型。它们有许多自定义类正在序列化的绑定[IgnoreDataMember]是静态的。我希望我的服务在运行时忽略一些数据成员