Files
XRLib/Assets/Scripts/UVC/Extention/SerializableEx.cs
2025-06-10 01:09:36 +09:00

214 lines
7.6 KiB
C#

#nullable enable
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace UVC.Extension
{
/// <summary>
/// 직렬화 관련 확장 메서드를 제공하는 클래스입니다.
/// </summary>
public static class SerializableEx
{
/// <summary>
/// 객체의 깊은 복사본을 생성합니다.
/// </summary>
/// <typeparam name="T">복사할 객체의 타입 (Serializable 속성이 필요)</typeparam>
/// <param name="source">복사할 원본 객체</param>
/// <returns>원본 객체의 깊은 복사본 또는 직렬화 불가능한 경우 기본값</returns>
/// <remarks>
/// 이 메서드는 BinaryFormatter를 사용하여 객체를 깊은 복사합니다.
/// 대상 타입은 반드시 [Serializable] 속성을 가져야 합니다.
/// </remarks>
/// <example>
/// <code>
/// [Serializable]
/// public class Person
/// {
/// public string Name { get; set; }
/// public int Age { get; set; }
/// }
///
/// // 사용 예시
/// var original = new Person { Name = "홍길동", Age = 30 };
/// var copy = original.DeepCopy();
///
/// // copy는 original과 동일한 값을 가지지만 서로 다른 메모리 참조
/// copy.Name = "김철수"; // original.Name은 여전히 "홍길동"
/// </code>
/// </example>
public static T? DeepCopy<T>(this T source)// where T : new()
{
if (!typeof(T).IsSerializable)
{
return default(T);// 직렬화 불가능한 경우 기본값 반환
}
try
{
object result = null;
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, source);// 객체를 메모리 스트림에 직렬화
ms.Position = 0;// 스트림 위치 초기화
result = (T)formatter.Deserialize(ms);// 역직렬화하여 새 객체 생성
ms.Close();// 스트림 닫기
}
return (T)result;
}
catch (Exception ex)
{
return default(T);// 예외 발생 시 기본값 반환
}
}
/// <summary>
/// 객체를 바이트 배열로 직렬화합니다.
/// </summary>
/// <typeparam name="T">직렬화할 객체의 타입 (Serializable 속성이 필요)</typeparam>
/// <param name="obj">직렬화할 객체</param>
/// <returns>직렬화된 바이트 배열 또는 실패 시 null</returns>
/// <example>
/// <code>
/// [Serializable]
/// public class Person
/// {
/// public string Name { get; set; }
/// public int Age { get; set; }
/// }
///
/// // 사용 예시
/// var person = new Person { Name = "홍길동", Age = 30 };
/// byte[] data = person.SerializeToBytes();
/// // 직렬화된 바이트 배열을 저장하거나 네트워크 전송 가능
/// </code>
/// </example>
public static byte[] SerializeToBytes<T>(this T obj) where T : class
{
if (obj == null || !typeof(T).IsSerializable)
return null;
try
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
return ms.ToArray();
}
}
catch (Exception)
{
return null;
}
}
/// <summary>
/// 바이트 배열에서 객체로 역직렬화합니다.
/// </summary>
/// <typeparam name="T">역직렬화할 객체 타입 (Serializable 속성이 필요)</typeparam>
/// <param name="bytes">역직렬화할 바이트 배열</param>
/// <returns>역직렬화된 객체 또는 실패 시 null</returns>
/// <example>
/// <code>
/// // 바이트 배열에서 객체 복원
/// byte[] savedData = GetSavedDataFromSomewhere();
/// Person restoredPerson = savedData.DeserializeFromBytes<Person>();
///
/// if (restoredPerson != null)
/// {
/// Console.WriteLine($"이름: {restoredPerson.Name}, 나이: {restoredPerson.Age}");
/// }
/// </code>
/// </example>
public static T DeserializeFromBytes<T>(this byte[] bytes) where T : class
{
if (bytes == null || bytes.Length == 0 || !typeof(T).IsSerializable)
return null;
try
{
using (var ms = new MemoryStream(bytes))
{
var formatter = new BinaryFormatter();
return (T)formatter.Deserialize(ms);
}
}
catch (Exception)
{
return null;
}
}
/// <summary>
/// 객체를 파일에 직렬화하여 저장합니다.
/// </summary>
/// <typeparam name="T">직렬화할 객체의 타입 (Serializable 속성이 필요)</typeparam>
/// <param name="obj">저장할 객체</param>
/// <param name="filePath">저장할 파일 경로</param>
/// <returns>성공 여부</returns>
/// <example>
/// <code>
/// var settings = new GameSettings { Volume = 0.8f, Difficulty = "Hard" };
/// bool success = settings.SerializeToFile("Assets/settings.dat");
/// </code>
/// </example>
public static bool SerializeToFile<T>(this T obj, string filePath) where T : class
{
if (obj == null || !typeof(T).IsSerializable || string.IsNullOrEmpty(filePath))
return false;
try
{
using (var fs = new FileStream(filePath, FileMode.Create))
{
var formatter = new BinaryFormatter();
formatter.Serialize(fs, obj);
return true;
}
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 파일에서 객체를 역직렬화하여 로드합니다.
/// </summary>
/// <typeparam name="T">역직렬화할 객체 타입 (Serializable 속성이 필요)</typeparam>
/// <param name="filePath">로드할 파일 경로</param>
/// <returns>역직렬화된 객체 또는 실패 시 null</returns>
/// <example>
/// <code>
/// GameSettings settings = DeserializeFromFile<GameSettings>("Assets/settings.dat");
/// if (settings != null)
/// {
/// ApplySettings(settings.Volume, settings.Difficulty);
/// }
/// </code>
/// </example>
public static T DeserializeFromFile<T>(string filePath) where T : class
{
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath) || !typeof(T).IsSerializable)
return null;
try
{
using (var fs = new FileStream(filePath, FileMode.Open))
{
var formatter = new BinaryFormatter();
return (T)formatter.Deserialize(fs);
}
}
catch (Exception)
{
return null;
}
}
}
}