C# - object를 QueryString으로 직렬화하는 방법
간혹 QueryString 문자열을 구해야 하는 경우가 있는데요, 물론 검색해 보면 많은 코드들이 있습니다.
How do I serialize an object into query-string format?
; https://stackoverflow.com/questions/6848296/how-do-i-serialize-an-object-into-query-string-format
이에 기반해 다음과 같이 간단하게 만들 수 있고,
internal static class ObjectExtension
{
static ConcurrentDictionary<Type, PropertyInfo[]> _typePropertyCache = new ConcurrentDictionary<Type, PropertyInfo[]>();
public static string ToQueryString(this object obj)
{
Type type = obj.GetType();
if (_typePropertyCache.TryGetValue(type, out var propInfo) == false)
{
propInfo = (from prop in type.GetProperties()
where prop.CanRead == true
select prop).ToArray();
_typePropertyCache.TryAdd(type, propInfo);
}
var queryArray = from prop in propInfo
select prop.Name + "=" + HttpUtility.UrlEncode(prop.GetValue(obj, null)?.ToString());
return string.Join("&", queryArray);
}
}
이런 식으로 쓸 수 있습니다.
namespace ConsoleApp1;
internal class Program
{
static void Main(string[] args)
{
Test v = new Test
{
Name = "test",
Age = 10,
Birthday = DateTime.Now
};
Console.WriteLine(v.ToQueryString());
// 출력 결과: Name=test&Age=10&Birthday=2023-12-19+%ec%98%a4%ed%9b%84+11%3a08%3a57
}
}
public class Test
{
public string Name { get; set; } = "";
public int Age { get; set; }
public DateTime Birthday { get; set; }
}
그런데, 혹시 QueryString을 위한 Source Generator라도 있지 않을까요? 아쉽게도 ^^ 검색했지만 찾을 수 없었습니다.
만들자니 귀찮군요, 요즘
너무 야크 털을 깎아서,,, 그렇다면 혹시나 차선책으로 기존의 Serializer처럼 타입마다 전용 Writer를 동적으로 생성해 사용하는 것이 있지 않을까... 싶었는데요, 오호~~~ 정말 있습니다. ^^
WebSerializer
; https://github.com/Cysharp/WebSerializer
사용법은 역시 간단합니다.
using Cysharp.Web; // Install-Package WebSerializer
namespace ConsoleApp1;
internal class Program
{
static void Main(string[] args)
{
Test v = new Test
{
Name = "test",
Age = 10,
Birthday = DateTime.Now
};
Console.WriteLine(WebSerializer.ToQueryString(v));
}
}
당연히 성능도 좋을 텐데요, 제 컴퓨터에서 저 2개의 소스 코드를 1_000_000번 루프를 돌렸더니,
[ObjectExtension.ToQueryString]
00:00:00.8749938
[WebSerializer.ToQueryString]
00:00:00.3657905
WebSerializer가 2.4배 가까이 빠른 속도를 보입니다. ^^
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]