본문 바로가기
CODING/C#

C# 직렬화(Serialization)

by marketingsj 2022. 9. 21.

https://github.com/nocturover/CSLearning/tree/master/03_Serialize/SerializeConsoleApp

 

GitHub - nocturover/CSLearning

Contribute to nocturover/CSLearning development by creating an account on GitHub.

github.com

1.

C#에서는 using System.Xml.Serialization; namespace에서 직렬화를 제공한다.

 

2. 직렬화의 정의

https://ko.wikipedia.org/wiki/%EC%A7%81%EB%A0%AC%ED%99%94

직렬화(直列化) 또는 시리얼라이제이션(serialization)은 컴퓨터 과학의 데이터 스토리지 문맥에서 데이터 구조 오브젝트 상태를 동일하거나 다른 컴퓨터 환경에 저장(이를테면 파일이나 메모리 버퍼에서, 또는 네트워크 연결 링크 간 전송)하고 나중에 재구성할 수 있는 포맷으로 변환하는 과정이다.[1]

오브젝트를 직렬화하는 과정은 오브젝트를 마샬링한다고도 한다.[2] 반대로, 일련의 바이트로부터 데이터 구조를 추출하는 일은 역직렬화 또는 디시리얼라이제이션(deserialization)이라고 한다.

 

2.2

직렬화(마샬링, Serialization)는 컴퓨터 스토리지에 데이터(파일, 버퍼)를 저장하고 역직렬화를 통해 해당 구조를 추출할 수 있다.

 

3.

using System.Xml.Serialization;

namespace Serializer
{
    class Program
    {
        ''''''
    }
    class SerializeUtil
    {
        public bool Logging { get; set; }
        public SerializeUtil()
        {
            this.Logging = true;
        }
        public void Serialize<T>(T target, string filename)
        {
            var ser = new XmlSerializer(typeof(T));

            using (var sw = new StreamWriter(filename))
            {
                ser.Serialize(sw, target);
                if (IsDuplicated(filename))
                {
                    Console.Write("this file name is duplicated, do you want to overwrite? ");
                    string? ans = Console.ReadLine();
                    if (string.IsNullOrEmpty(ans) || ans.StartsWith("n", StringComparison.OrdinalIgnoreCase))
                        return;
                }
                if (Logging)
                {
                    LogWithTime($"Complete to serialize '{typeof(T).Name} - {filename.Split('\\').Last()}'");
                }
            }
            bool IsDuplicated(string filename)
            {
                string[] files = Directory.GetFiles(string.Join('\\', filename.Split('\\')[0..^1]));
                if (files.Any(o => o.Equals(filename)))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        public void Deserialize<T>(string filename, out T? target)
        {
            target = default;
            var ser = new XmlSerializer(typeof(object));
            using (FileStream fs = new FileStream(filename, FileMode.Open))
            {
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
                target = (T)ser.Deserialize(fs);
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
            }
            if (Logging)
            {
                if (target == null)
                {
                    LogWithTime($"File is null '{typeof(T).Name} - {nameof(target)}'");
                }
                else
                {
                    LogWithTime($"Complete to Deserialize '{typeof(T).Name} - {nameof(target)}'");
                }
            }
        }
        private void LogWithTime(string message)
        {
            Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss:fff")}] {message}");
        }
    }
}

3.1

SerializeUtil 클래스는 (역)직렬 대상의 형식과 경로를 문자열로 입력받아 (역)직렬을 수행 할 수 있으며, 콘솔 어플리케이션에서 시간과 성공여부에 대한 로그를 기록한다.

 

3.2 동작방식

직렬화에서 가장 중요한 부분은 명시적으로 형식을 XmlSerializer 클래스에 초기값으로 전달해주는 것이다.

public class XmlSerializer
// Serializes and deserializes objects into and from XML documents. The System.Xml.Serialization.XmlSerializer
// enables you to control how objects are encoded into XML.

XmlSerializer Constructor
// // Summary:
// Initializes a new instance of the System.Xml.Serialization.XmlSerializer class
// that can serialize objects of the specified type into XML documents, and deserialize
// XML documents into objects of the specified type.
// // Parameters:
// type:
// The type of the object that this System.Xml.Serialization.XmlSerializer can serialize.

*지정된 형식에 대한 (역)직렬화 가능

 

using System.Xml.Serialization;

namespace Serializer
{
    class Program
    {
        static void Main(string[] args)
        {
            var serUtil = new SerializeUtil();

            List<int> numbers = GenerateRandomNums();
            Console.WriteLine(new String('-', 30) 
                + "\nList is Generated! - " + string.Join(',', numbers) + '\n' 
                + new String('-', 30));
            serUtil.Serialize(numbers, @"C:\Users\pi623\Desktop\ser.xml");
        }
        private static List<int> GenerateRandomNums()
        {
            List<int> nums = new();
            Random random = new Random();
            int size = random.Next(1, 10);
            for (int idx = 0; idx < size; idx++)
            {
                nums.Add(random.Next(1, 100));
            }
            size = default(int);
            return nums;
        }
    }
    class SerializeUtil
    {
        ''''''
    }
}

3.3

해당 Serializer Namespace의 진입점은 Main 함수이다.

직렬화 대상이 될 난수 리스트를 생성한다.

생성한 SerializeUtil의 인스턴스로부터 함수((역)직렬화)를 사용한다.

 

4. 사용

역직렬화를 이용하여 수동적으로 파일을 열람하여 데이터를 임시로 생성된 지정타입의 멤버에 반복문 등을 통해 개별적으로 할당해 줄 필요없이 바로 데이터가 복원될 수 있다는 점에서 이점이 있다.

댓글