我希望序列化一个具有DataMember属性的对象,以便在某些属性上忽略它。
假设我有自定义属性MyIgnoreDataMember。
我希望用它标记的属性对于我的自定义DataContractSerializer是不可见的,但是对于普通的DataContractSerializer是可见的。
而且我必须使用DataContractSerializer和其他任何东西。
代码是Silverlight应用程序。
有人成功地对DataContractSerializer进行了子类化吗?
发布于 2017-02-26 19:13:34
对您的问题的回答因下列问题而变得复杂:
DataContractSerializer是密封的,所以不能用子类来检查像MyIgnoreDataMember这样的属性。DataContractSerializer不支持ShouldSerialize模式,正如解释的这里那样,所以您不能仅仅通过回调方法来抑制不想要的属性的序列化。那么,你有什么选择?假设您的对象图如下所示:
[DataContract(Name = "Root", Namespace = "http://www.MyNamespace.com")]
public class RootObject
{
[DataMember]
public NestedObject NestedObject { get; set; }
}
[DataContract(Name = "Nested", Namespace = "http://www.MyNamespace.com")]
public class NestedObject
{
[DataMember]
public string SensitiveData { get; set; }
[DataMember]
public string PublicData { get; set; }
}您希望有条件地抑制SensitiveData的输出。然后有以下几种可能性:
EmitDefaultValue = false标记它们,并在某些线程静态为true时返回一个默认值,例如:
(名称=“根”,命名空间= "http://www.MyNamespace.com")公共类RootObject { DataMember public NestedObject NestedObject { get;set;}DataContract(名称=“嵌套”,命名空间= "http://www.MyNamespace.com")公共类NestedObject { string sensitiveData;DataMember(IsRequired = false,EmitDefaultValue = false)公共字符串SensitiveData { get { if (SerializationState.InCustomSerialization())返回空;返回sensitiveData;} set { sensitiveData = value;} DataMember公共字符串PublicData { get;set;}公共静态类SerializationState { ThreadStatic静态bool inCustomSerialization;公共静态bool InCustomSerialization() {返回inCustomSerialization;} public静态IDisposable SetInCustomDeserialization(bool值){返回新的PushValue (值,() => inCustomSerialization,b => inCustomSerialization = b);}公共结构PushValue: IDisposable { Action setValue;T oldValue;public PushValue(T值,Func getValue,Action setValue) { if (getValue == null ?x setValue setValue null)抛出新的getValue();=;=();setValue(value);} #region IDisposable成员//通过使用一次性结构,我们避免了分配和释放可终结类实例的开销。公开的void (){ if (setValue != null) setValue(oldValue);}
然后,在序列化时,执行如下操作:
使用(SerializationState.SetInCustomDeserialization(true)) { //序列化和数据契约序列化程序。}
老实说挺丑的。DataContractSerializer自己进行映射,因为合同名称和名称空间是相同的。也就是说-将实际的根对象序列化为XML字符串(或XDocument,如下所示),将中间XML反序列化为DTO根,然后序列化出DTO。XDocument (其中的以silverlight提供。):
公共静态部分类DataContractSerializerHelper {公共静态XDocument SerializeContractToXDocument(此T){返回obj.SerializeContractToXDocument(null);}公共静态XDocument SerializeContractToXDocument(此T,DataContractSerializer序列化程序){ var doc =新XDocument();使用(var null= doc.CreateWriter()) {(序列化器?新DataContractSerializer(obj.GetType())).WriteObject(writer,obj);}返回doc;}公共静态T DeserializeContract(此XDocument文档){返回doc.DeserializeContract( null);}公共静态T DeserializeContract(此XDocument文档,DataContractSerializer序列化程序){ if (doc == null)抛出新ArgumentNullException();使用(var reader = doc.CreateReader()) {返回(T)(序列化程序?新DataContractSerializer(typeof(T))).ReadObject(reader);}}
接下来,使用XPATH查询修剪不想要的元素,然后将XDocument序列化为最终的XDocument表示。ElementSkippingXmlTextWriter从这个答案中删除编写时不想要的元素。https://stackoverflow.com/questions/42460674
复制相似问题