当前位置:   article > 正文

C#对象序列化_c# 序列化

c# 序列化

C# 对象序列化三种方式

一、常规序列化方式

对象标记为可序列化,然后把不需要序列化的字段加上[NonSerialized]特性

序列化测试对象SerializeTest

	[Serializable]
    public class SerializeTest
    {
        
        [NonSerialized]
        private string _name;

        public SerializeTest(string name, string ip, int port, ITestInfo testInfo)
        {
            Name = name;
            IP = ip;
            Port = port;
            TestInfo = testInfo;
        }

        public string Name { get { return _name; } set { _name = value; } }

        public string IP { get; set; }

        public int Port { get; set; }

        public ITestInfo TestInfo { get; set; }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

序列化对象包含的对象接口

    public interface ITestInfo
    {
        string Message { get; set; }

        int Id { get; set; }

        List<string> InfoList { get; set; }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

序列化对象包含的对象接口实现

    [Serializable]
	public class TestInfo : ITestInfo
    {
        public TestInfo(string message, int id, List<string> infoList)
        {
            Message = message;
            Id = id;
            InfoList = infoList;
        }

        public string Message { get; set; }
        public int Id { get; set; }
        public List<string> InfoList { get; set; }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

然后通过窗体的保存按钮进行对象序列化,加载时反序列化,进行测试,代码如下:

   public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var serializeTest = SerializeUtils.DeserializeBinaryFromFile("F:\\temp\\test.dat");
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ITestInfo testInfo = new TestInfo("消息",1,new List<string> { "测试","121"});
            SerializeTest serializeTest = new SerializeTest("序列化测试","127.0.0.1",8080,testInfo);
            SerializeUtils.SerializeBinaryToFile(serializeTest, "F:\\temp\\test.dat");
        }
       
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

序列化工具类

 public class SerializeUtils
    {
        public static object DeserializeBinaryFromFile(string file)
        {
            FileStream fs = null;
            try
            {
                fs = new FileStream(file, FileMode.Open, FileAccess.ReadWrite);

                BinaryFormatter deserializer = new BinaryFormatter();
                object newobj = deserializer.Deserialize(fs);

                fs.Close();
                return newobj;
            }
            catch (Exception ex)
            {
                if (fs != null) fs.Close();
                return null;
            }
        }

        public static bool SerializeBinaryToFile(object request, string file)
        {
            try
            {
                BinaryFormatter serializer = new BinaryFormatter();
                FileStream fs = new FileStream(file, FileMode.Create, FileAccess.ReadWrite);
                serializer.FilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Low;
                serializer.Serialize(fs, request);
                fs.Close();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

测试结果如下:

点击保存待保存对象截图:
在这里插入图片描述

重新启动反序列化结果如下:
在这里插入图片描述

Name为null,没有保存
  • 1

二、实现ISerializable接口

通过实现ISerializable接口的GetObjectData方法,把需要序列化保存的数据通过info.AddValue方法进行添加,此时不需要使用特性 [NonSerialized]
添加有参构造来实现对象的数据的获取

将SerializeTest类改造如下

[Serializable]
public class SerializeTest : ISerializable
{
    public SerializeTest(string name, string ip, int port, ITestInfo testInfo)
    {
        Name = name;
        IP = ip;
        Port = port;
        TestInfo = testInfo;
    }

    public string Name { get; set; }

    public string IP { get; set; }

    public int Port { get; set; }

    public ITestInfo TestInfo { get; set; }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("IP", this.IP);
        info.AddValue("Port", this.Port);
        info.AddValue("TestInfo", this.TestInfo);
    }

    protected SerializeTest(SerializationInfo info, StreamingContext context)
    {
        try
        {
            SerializationInfoEnumerator enumerator = info.GetEnumerator();
            this.IP = GetValueBySerializationInfo<string>(info, "IP");
            this.Port = GetValueBySerializationInfo<int>(info, "Port");
            while (enumerator.MoveNext())
            {
                if (enumerator.Name == "TestInfo") this.TestInfo = (ITestInfo)enumerator.Value;
            }
        }
        catch (Exception e)
        {
        }
    }

    /// <summary>
    /// 根据key从序列化对象获取值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="info"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public T GetValueBySerializationInfo<T>(SerializationInfo info, string key)
    {
        try
        {
            return (T)info.GetValue(key, typeof(T));
        }
        catch
        {
            return default(T);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

删除test.dat文件重新测试,测试结果一致。

三、通过反射方式

在方式二的基础上通过反射自动将需要序列化的数据进行保存和获取,注意此方式将不需要序列化的属性使用特性[XmlIgnore]标记,对于需要序列化的属性较多时效果较好,SerializeTest类改造如下:

[Serializable]
public class SerializeTest : ISerializable
{
    public SerializeTest(string name, string ip, int port, ITestInfo testInfo)
    {
        Name = name;
        IP = ip;
        Port = port;
        TestInfo = testInfo;
        TestInfo = testInfo;
    }
    [XmlIgnore]
    public string Name { get; set; }

    public string IP { get; set; }

    public int Port { get; set; }
    public ITestInfo TestInfo { get; set; }


    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        var properties = GetProperties();
        foreach (var property in properties)
        {
            if (IsNeedSerializedProperty(property))
            {
                info.AddValue(property.Name, GetPropertyValue(property));
            }
        }
    }

    protected SerializeTest(SerializationInfo info, StreamingContext context)
    {
        try
        {
            var properties = GetProperties();
            foreach (var property in properties)
            {
                if (IsNeedSerializedProperty(property))
                {
                    try
                    {
                        SetPropertyValue(property, GetValueBySerializationInfo<object>(info, property.Name));
                    }
                    catch (Exception ex)
                    {

                    }
                }
            }
        }
        catch (Exception e)
        {
        }
    }
    private PropertyInfo[] GetProperties()
    {
        return this.GetType().GetProperties();
    }
    /// <summary>
    /// 属性是否可序列化
    /// </summary>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    private bool IsNeedSerializedProperty(PropertyInfo propertyInfo)
    {
        if (propertyInfo == null) return false;
        return propertyInfo.GetCustomAttribute(typeof(XmlIgnoreAttribute)) == null
                && propertyInfo.CanWrite;
    }
    private object GetPropertyValue(PropertyInfo propertyInfo)
    {
        if (propertyInfo == null) return null;
        return this.GetType().GetProperty(propertyInfo.Name).GetValue(this, null);
    }
    private void SetPropertyValue(PropertyInfo propertyInfo, object value)
    {
        if (propertyInfo == null) return;
        this.GetType().GetProperty(propertyInfo.Name).SetValue(this, value);
    }
    /// <summary>
    /// 根据key从序列化对象获取值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="info"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public T GetValueBySerializationInfo<T>(SerializationInfo info, string key)
    {
        try
        {
            return (T)info.GetValue(key, typeof(T));
        }
        catch
        {
            return default(T);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100

删除test.dat文件重新测试,测试结果一致。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/111871?site
推荐阅读
相关标签
  

闽ICP备14008679号