상세 컨텐츠

본문 제목

.NET Serialization 닷넷 객체직렬화

C#

by 메타샤워 2023. 7. 18. 18:44

본문

.NET Serialization

 
클래스 객체의 데이터를 파일이나 Database에 저장하거나, 웹서비스 등으로 네트워크 상으로 전송할수 있는데 
이를 Serialization 직렬화 라고 한다.  이렇게 저장 혹은 전송된 결과는 다시 그대로 메모리상의 클래스 객체로 가져올수 있는데 이것은 Deserialization 역직렬화 라고 한다.
.NET 에서는 저장 포멧에 따라서 크게 3가지 방식의 Serialization 직렬화가 제공된다.
1.XML Serialization
2. Soap Serialization
3. Binary Serialization 
 

XML Serialization 

XML Serialization은 클래스 객체 데이터를 XML 포멧으로 저장하는데, 특히 public멤버만 저장한다.
즉, public이 아닌 필드/소고성은 저장되지 않는다.
(* 이렇게 public 멤버만 저장하는것을 Shallow Serialization 얕은 직렬화 라고 부르며, 모든 멤버를 다 저장하는것은 
Deep Serialization 깊은 직렬화라고 부른다. 
XML Serialization은 Shallow Serialization을 구현한다.)
 또한  Serialization할 클래스는 public 으로 선언되어져야 하며, Deserialization을 위해 파라미터가 없는 생성자를 가져야 한다.
using System.IO;  
using System.Xml.Serialization;  
  
namespace Serial  
{  
    // XML Serialzation  
    public class Person  // 클래스는 public 이어야  
    {  
        // public 멤버만 저장  
        public string Name;  
        public int? Height;  
        public int Age  
        {  
            get { return _age; }  
            set { if (value >= 0) _age = value; }  
        }  
  
        // private 멤머이므로 저장 안함  
        private int avgWeight;  
        private int _age;  
  
        public Person()  
        {  
        }  
  
        public override string ToString()  
        {  
            return string.Format("{0}: {1}", Name, Age);  
        }  
    }  
  
    class PersonTest  
    {  
        private string xmlFilename = @"C:\temp\test.xml";  
  
        public void SerializePerson()  
        {  
            Person objPerson = new Person();  
            objPerson.Name = "홍길동";  
            objPerson.Age = 26;  
  
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person));  
            using (StreamWriter wr = new StreamWriter(xmlFilename))  
            {  
                xmlSerializer.Serialize(wr, objPerson);  
            }              
        }  
  
        public Person DeserializePerson()  
        {  
            Person p;  
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person));  
            using (StreamReader rdr = new StreamReader(xmlFilename))  
            {  
                p = (Person)xmlSerializer.Deserialize(rdr);  
            }  
            return p;  
        }  
    }  
}
-> 저장된 XML파일
<?xml version="1.0" encoding="utf-8"?>  
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
  <Name>홍길동</Name>  
  <Height xsi:nil="true" />  
  <Age>26</Age>  
</Person>

 

 

SoapFormatter Serialization 

 
SoapFormatter Serialization은 SOAP ( Simple Object Access Protocol ) 포멧으로(XML형태) 클래스 객체를 Serialize해서 저장한다. SOAP 포멧은 웹 서비스를 통해 데이터를 주고 받을 때 많이 사용된다. 
SoapFomatter와 Binary Serialization을 사용하기 위해서는 클래스 선언문위에
[Serializable[이라는 Attribute를 붙여야 한다. XML Serialization과는 달리, 클래스가 public일 필요가 없으며 public멤버 뿐만 아니라 모든 멤버들을 Serialize한다. 
(* SoapFormatter Serialization은 DeepSerialization을 구혀한다.)
BinaryFormatter와는 다르게 SoapFormatter는 Generic Type를 저장할 수 없다.
using System;  
using System.IO;  
using System.Runtime.Serialization.Formatters.Soap;  
  
namespace Serial  
{  
    // SoapFormatter Serialzation  
    [Serializable]  
    class Person  
    {  
        public string Name;  
          
        // Soap Serailization은 Generic Type을   
        // 지원하지 않는다.   
        // int? 은 Nullable<int>이므로 에러 발생함.  
        //public int? Height;  
  
        public int Age  
        {  
            get { return _age; }  
            set { if (value >= 0) _age = value; }  
        }  
  
        //Serialize를 원하지 않는 필드는  
        //아래 NonSerialized Attribute를 표시  
        [NonSerialized] private int avgWeight;  
  
        private int _age;  
  
        public Person()  
        {  
        }  
  
        public override string ToString()  
        {  
            return string.Format("{0}: {1}", Name, Age);  
        }  
    }  
  
    class PersonTest  
    {  
        private string xmlFilename = @"C:\temp\test.xml";  
  
        public void SerializePerson()  
        {  
            Person objPerson = new Person();  
            objPerson.Name = "홍길동";  
            objPerson.Age = 26;  
  
            SoapFormatter soapFmt = new SoapFormatter();  
            using (FileStream fs = new FileStream(xmlFilename, FileMode.Create))  
            {  
                soapFmt.Serialize(fs, objPerson);  
            }  
        }  
  
        public Person DeserializePerson()  
        {  
            Person p;  
            SoapFormatter soapFmt = new SoapFormatter(); ;  
            using (FileStream rdr = new FileStream(xmlFilename, FileMode.Open))  
            {  
                p = (Person)soapFmt.Deserialize(rdr);  
            }  
            return p;  
        }  
    }  
}
-> SOAP XML 포멧으로 저장된 내용
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">  
<SOAP-ENV:Body>  
<a1:Person id="ref-1" 
xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Serial/Serial%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">  
<Name id="ref-3">홍길동</Name>  
<_age>26</_age>  
</a1:Person>  
</SOAP-ENV:Body>  
</SOAP-ENV:Envelope>

BinaryFormatter Serialization 

BinaryFormatter Serialization은 .NET Framework 고유의방식으로 클래스 객체를 Serialize 해서 저장한다.
즉 .NET에서만 사용되며, SOAP과 다르게 타 시스템과 호환성을 제공하지 않는다.
클래스 선언문 위에 [Serializable]이라는 Attribute를 붙여야 하며,
모든 멤버들을 Serialize한다. (* Deep Serialization을 구현함 )
BinaryFormatter는 SoapFormatter에서 저장할 수 없는 Generic Type도 저장할 수 있다.
상대적으로 Output 크기가 적으며 속도도 다른 Serialization방식보다 빠른편이다.
using System;  
using System.IO;  
using System.Runtime.Serialization.Formatters.Binary;  
  
namespace Serial  
{  
    // BinaryFormatter Serialzation  
    [Serializable]  
    class Person  
    {  
        public string Name;  
  
        // Binary Serailization은 Generic Type을   
        // 지원한다.          
        public Nullable<int> Height;  
  
        public int Age  
        {  
            get { return _age; }  
            set { if (value >= 0) _age = value; }  
        }  
  
        //Serialize를 원하지 않는 필드는  
        //아래 NonSerialized Attribute를 표시  
        [NonSerialized]  
        private int avgWeight;  
  
        private int _age;  
  
        public Person()  
        {  
        }  
  
        public override string ToString()  
        {  
            return string.Format("{0}: {1}", Name, Age);  
        }  
    }  
  
    class PersonTest  
    {  
        private string xmlFilename = @"C:\temp\test.dat";  
  
        public void SerializePerson()  
        {  
            Person objPerson = new Person();  
            objPerson.Name = "홍길동";  
            objPerson.Age = 26;  
            objPerson.Height = 6;  
  
            BinaryFormatter binFmt = new BinaryFormatter();  
            using (FileStream fs = new FileStream(xmlFilename, FileMode.Create))  
            {  
                binFmt.Serialize(fs, objPerson);  
            }  
        }  
  
        public Person DeserializePerson()  
        {  
            Person p;  
            BinaryFormatter binFmt = new BinaryFormatter(); ;  
            using (FileStream rdr = new FileStream(xmlFilename, FileMode.Open))  
            {  
                p = (Person)binFmt.Deserialize(rdr);  
            }  
            return p;  
        }  
    }  
}

관련글 더보기