[C#] 12.1 직렬화

C#에서는 ISerializable 어튜리뷰트를 제공하고 있으며 이를 사용하면 별다른 작업없이 직렬화할 수 있습니다. 직렬화하려면 어느 개체 정보를 직렬화할 것인지 어느 매체에 직렬화할 것인지 결정합니다. 그리고 C#에서는 직렬화할 때 어떠한 포멧으로 직렬화할 것인지에 따라 포멧터를 이용하여 직렬화를 수행합니다.

먼저 특정 형식의 개체를 직렬화하려면 해당 개체는 직렬화 가능한 대상이어야 합니다. 특정 형식의 개체를 직렬화할 수 있게 정의하려면 ISerializable 어튜리뷰트를 지정합니다.

[Serializable]
class Man
{
    internal string Name
    {
        get;
        private set;
    }
    internal int Age
    {
        get;
        private set;
    }
    internal Man(string name, int age)
    {
        Name = name;
        Age = age;
    }
    public override string ToString()
    {
        return string.Format("이름:{0} 나이:{1}", Name, Age);
    }
}

그리고 직렬화를 할 때는 포멧터를 사용합니다. C#에서 제공하는 포멧터에는 바이너리 포멧터와 Soap 포멧터 등이 있습니다. 바이너리 포멧터는 개체의 정보를 그대로 직렬화하고 Soap 포멧터는 개체의 정보를 xml 형태의 태그로 메터 데이터와 함께 값을 표현하고 이러한 정보를 Soap으로 감싸(Envelop) 직렬화합니다.

직렬화할 때는 포멧터의 Serialize 메서드에 직렬화 대상 매체와 대상 개체를 전달합니다.

Man man = new Man("홍길동", 29); //직렬화 대상 개체
FileStream fs = new FileStream("man.txt",FileMode.Create); //직렬화 대상 매체
BinaryFormatter bf = new BinaryFormatter(); //포멧터
bf.Serialize(fs, man); //직렬화 수행
fs.Close();

그리고 역직렬화는 포멧터의 DeSerialize 메서드에 대상 매체를 전달하면 역직렬화하여 개체를 반환합니다. 반환 형식은 object이며 실제 직렬화했던 대상 개체 형식으로 변환하여 사용합니다.

FileStream fs2 = new FileStream("man.txt", FileMode.Open);//대상 매체
BinaryFormatter bf2 = new BinaryFormatter(); //포멧터
Man man2 = bf2.Deserialize(fs2) as Man; //역직렬화
fs2.Close();

다음은 Binary 포멧터로 직렬화와 역직렬화를 제대로 수행하는지 확인하는 예제 코드입니다.

static void Main(string[] args)
{
    Man man = new Man("홍길동", 29); //직렬화 대상 개체
    FileStream fs = new FileStream("man.txt",FileMode.Create); //직렬화 대상 매체
    BinaryFormatter bf = new BinaryFormatter(); //포멧터
    bf.Serialize(fs, man); //직렬화 수행
    fs.Close();

    FileStream fs2 = new FileStream("man.txt", FileMode.Open);//대상 매체
    BinaryFormatter bf2 = new BinaryFormatter(); //포멧터
    Man man2 = bf2.Deserialize(fs2) as Man; //역직렬화
    fs2.Close();

    Console.WriteLine(man2);
}

▶ 실행 결과

이름:홍길동 나이:29

프로젝트의 출력 폴더를 확인하면 man.txt 파일이 생긴 것을 알 수 있고 개체의 정보가 쓰여져 있음을 확인할 수 있습니다.

Soap 포멧터로 직렬화 및 역직렬화하는 것도 바이너리 포멧터로 하는 것과 같습니다. Soap 포멧터를 사용하려면 System.Runtime.Serialization.Formatters.Soap 어셈블리를 참조 추가해야 합니다.

[그림 12.1] Soap 포멧터 사용을 위해 어셈블리 참조 추가

 Soap 포멧터를 사용하여 직렬화 및 역직렬화 예제 코드입니다.

static void Main(string[] args)
{
    Man man = new Man("홍길동", 29); //직렬화 대상 개체
    FileStream fs = new FileStream("man.xml", FileMode.Create); //직렬화 대상 매체

    SoapFormatter sf = new SoapFormatter(); //포멧터
    sf.Serialize(fs, man); //직렬화 수행
    fs.Close();

    FileStream fs2 = new FileStream("man.xml", FileMode.Open);//대상 매체
    SoapFormatter sf2 = new SoapFormatter(); //포멧터
    Man man2 = sf2.Deserialize(fs2) as Man; //역직렬화
    fs2.Close();

    Console.WriteLine(man2);
}

출력 폴더에 만들어진 파일을 열어 보면 바이너리 포멧터를 사용할 때와 내용이 다름을 알 수 있습니다. 파일에 쓰여진 바이트 수를 확인해 보면 Soap 포멧터로 만들어진 파일이 큰 것을 알 수 있습니다.