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