Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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_Silverlight_Serialization_Datacontractserializer_Automapper - Fatal编程技术网

C# 自定义数据序列化程序

C# 自定义数据序列化程序,c#,.net,silverlight,serialization,datacontractserializer,automapper,C#,.net,Silverlight,Serialization,Datacontractserializer,Automapper,我想序列化在某些属性上具有要忽略的DataMember属性的对象 假设我有自定义属性MyIgnoreDataMember 我希望标记有它的属性对于自定义DataContractSerializer不可见,但对于普通DataContractSerializer可见 我必须使用DataContractSerializer,其他什么都不用 代码是Silverlight应用程序 有人成功地将DataContractSerializer子类化了吗?以下问题使问题的答案变得复杂: 是密封的,因此无法子类化以

我想序列化在某些属性上具有要忽略的DataMember属性的对象

假设我有自定义属性MyIgnoreDataMember

我希望标记有它的属性对于自定义DataContractSerializer不可见,但对于普通DataContractSerializer可见

我必须使用DataContractSerializer,其他什么都不用

代码是Silverlight应用程序


有人成功地将DataContractSerializer子类化了吗?

以下问题使问题的答案变得复杂:

  • 是密封的,因此无法子类化以检查类似于
    MyIgnoreDataMember
    的属性

  • 通常,在序列化过程中使用注入适当的对象图是一种方法——但silverlight上似乎没有,请参阅

  • 如前所述,
    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; }
    }
    
    您希望有条件地抑制
    敏感数据的输出。那么以下是可能性:

  • 如果您只需要删除一些属性,那么当某个线程静态为
    true
    时,您可以用标记它们并返回默认值,例如:

    [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
    {
        string sensitiveData;
    
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string SensitiveData
        {
            get
            {
                if (SerializationState.InCustomSerialization())
                    return null;
                return sensitiveData;
            }
            set
            {
                sensitiveData = value;
            }
        }
    
        [DataMember]
        public string PublicData { get; set; }
    }
    
    public static class SerializationState
    {
        [ThreadStatic]
        static bool inCustomSerialization;
    
        public static bool InCustomSerialization()
        {
            return inCustomSerialization;
        }
    
        public static IDisposable SetInCustomDeserialization(bool value)
        {
            return new PushValue<bool>(value, () => inCustomSerialization, b => inCustomSerialization = b);
        }
    }
    
    public struct PushValue<T> : IDisposable
    {
        Action<T> setValue;
        T oldValue;
    
        public PushValue(T value, Func<T> getValue, Action<T> setValue)
        {
            if (getValue == null || setValue == null)
                throw new ArgumentNullException();
            this.setValue = setValue;
            this.oldValue = getValue();
            setValue(value);
        }
    
        #region IDisposable Members
    
        // By using a disposable struct we avoid the overhead of allocating and freeing an instance of a finalizable class.
        public void Dispose()
        {
            if (setValue != null)
                setValue(oldValue);
        }
    
        #endregion
    }
    
    老实说,相当难看

  • 您可以使用与实际类型相同的合同名称和名称空间创建一个完整的DTO层次结构,使用类似的方法将实际类映射到DTO,并序列化DTO:

    [DataContract(Name = "Root", Namespace = "http://www.MyNamespace.com")]
    class RootObjectDTO
    {
        [DataMember]
        public NestedObjectDTO NestedObject { get; set; }
    }
    
    [DataContract(Name = "Nested", Namespace = "http://www.MyNamespace.com")]
    class NestedObjectDTO
    {
        [DataMember]
        public string PublicData { get; set; }
    }
    
    如果silverlight上没有automapper,则可以使用
    DataContractSerializer
    本身进行映射,因为契约名称和名称空间是相同的。即-将实际根对象序列化为XML字符串(或序列化为
    XDocument
    ,如下所示),将中间XML反序列化为DTO根,然后序列化出DTO

  • 您可以使用以下扩展类序列化到内存中的
    XDocument
    (它):

    public static partial class DataContractSerializerHelper
    {
        public static XDocument SerializeContractToXDocument<T>(this T obj)
        {
            return obj.SerializeContractToXDocument(null);
        }
    
        public static XDocument SerializeContractToXDocument<T>(this T obj, DataContractSerializer serializer)
        {
            var doc = new XDocument();
            using (var writer = doc.CreateWriter())
            {
                (serializer ?? new DataContractSerializer(obj.GetType())).WriteObject(writer, obj);
            }
            return doc;
        }
    
        public static T DeserializeContract<T>(this XDocument doc)
        {
            return doc.DeserializeContract<T>(null);
        }
    
        public static T DeserializeContract<T>(this XDocument doc, DataContractSerializer serializer)
        {
            if (doc == null)
                throw new ArgumentNullException();
            using (var reader = doc.CreateReader())
            {
                return (T)(serializer ?? new DataContractSerializer(typeof(T))).ReadObject(reader);
            }
        }
    }
    
    公共静态部分类DataContractSerializerHelper
    {
    公共静态XDocument文档(此T对象)
    {
    返回目标单据(空);
    }
    公共静态XDocument序列化ContractToxDocument(此T obj,DataContractSerializer序列化程序)
    {
    var doc=新的XDocument();
    使用(var writer=doc.CreateWriter())
    {
    (serializer??新的DataContractSerializer(obj.GetType()).WriteObject(writer,obj);
    }
    退货单;
    }
    公共静态T反序列化契约(此XDocument文档)
    {
    返回单据反序列化合同(空);
    }
    公共静态T反序列化契约(此XDocument文档、DataContractSerializer序列化程序)
    {
    如果(doc==null)
    抛出新ArgumentNullException();
    使用(var reader=doc.CreateReader())
    {
    return(T)(序列化程序??新的DataContractSerializer(typeof(T))).ReadObject(reader);
    }
    }
    }
    
    接下来,使用修剪不需要的元素,然后将
    XDocument
    序列化为最终的XML表示形式

  • 最后,如果性能和内存使用都很高,您可以使用
    ElementSkippingXmlTextWriter
    from在编写不需要的元素时删除它们


  • 使用序列化代理通常是一种方法,但是看起来它在Silverlight上是不可用的,请参阅。在缺少数据契约代理的情况下,您可能会考虑一种不同的方法:从代码中使用“EntEngSkpIPxxMLTEXTWRITER < /代码>,并在写入时跳过不需要的元素。所以不能被子类化。@dbc有趣。非常感谢。请把它作为答案贴出来
    public static partial class DataContractSerializerHelper
    {
        public static XDocument SerializeContractToXDocument<T>(this T obj)
        {
            return obj.SerializeContractToXDocument(null);
        }
    
        public static XDocument SerializeContractToXDocument<T>(this T obj, DataContractSerializer serializer)
        {
            var doc = new XDocument();
            using (var writer = doc.CreateWriter())
            {
                (serializer ?? new DataContractSerializer(obj.GetType())).WriteObject(writer, obj);
            }
            return doc;
        }
    
        public static T DeserializeContract<T>(this XDocument doc)
        {
            return doc.DeserializeContract<T>(null);
        }
    
        public static T DeserializeContract<T>(this XDocument doc, DataContractSerializer serializer)
        {
            if (doc == null)
                throw new ArgumentNullException();
            using (var reader = doc.CreateReader())
            {
                return (T)(serializer ?? new DataContractSerializer(typeof(T))).ReadObject(reader);
            }
        }
    }