Skip to content

Instantly share code, notes, and snippets.

@raveneer
Created January 6, 2018 13:17
Show Gist options
  • Save raveneer/0add786e71ce93761d65132563179d5c to your computer and use it in GitHub Desktop.
Save raveneer/0add786e71ce93761d65132563179d5c to your computer and use it in GitHub Desktop.
클래스명을 알고 있는 임의의 클래스를 Json을 이용해서 직렬/역직렬화 하는 클래스. Json.Net을 사용한다.
using System;
using System.Diagnostics;
using Newtonsoft.Json;
using NUnit.Framework;
namespace UnitTestProject
{
internal class Test_ComponentGenerator
{
[Test]
public void MakeNewComponentWithJson_1()
{
var jsonString = @"{""TypeName"":""UnitTestProject.SomeDog"",""Json"":""{\""BitePower\"":10.0}""}";
var newComponent = AnonymousClassJsonParser.MakeNewClassOrNull(jsonString);
Assert.IsTrue(newComponent is SomeDog);
Assert.AreEqual(10, ((SomeDog) newComponent).BitePower);
}
[Test]
public void MakeNewComponentWithJson_2()
{
var jsonString = @"{""TypeName"":""UnitTestProject.SomeCat"",""Json"":""{\""ScratchPower\"":5.0}""}";
var newComponent = AnonymousClassJsonParser.MakeNewClassOrNull(jsonString);
Assert.IsTrue(newComponent is SomeCat);
Assert.AreEqual(5, ((SomeCat) newComponent).ScratchPower);
}
[Test]
public void MakeNestedJsonFromIComponent()
{
var fido = new SomeDog {BitePower = 10};
var json = AnonymousClassJsonParser.MakeNestedJson(fido);
var expected = @"{""TypeName"":""UnitTestProject.SomeDog"",""Json"":""{\""BitePower\"":10.0}""}";
Assert.AreEqual(expected, json);
}
[Test]
public void SelialAndDeselial()
{
var fido = new SomeDog {BitePower = 10};
var jsonString = AnonymousClassJsonParser.MakeNestedJson(fido);
var newComponent = AnonymousClassJsonParser.MakeNewClassOrNull(jsonString);
Assert.AreEqual(fido.GetType(), newComponent.GetType());
Assert.AreEqual(fido.BitePower, ((SomeDog) newComponent).BitePower);
}
[Timeout(500)]
[Test]
[Ignore("1만개에 500ms 정도로 매우 빠름.")]
public void Performance_Serialize()
{
var fido = new SomeDog {BitePower = 10};
for (var i = 0; i < 10000; i++)
{
var jsonString = AnonymousClassJsonParser.MakeNestedJson(fido);
}
}
[Timeout(300)]
[Test]
[Ignore("1만개에 300ms 정도로 매우 빠름.")]
public void Performance_DeSerialize()
{
var jsonString = @"{""TypeName"":""UnitTestProject.SomeCat"",""Json"":""{\""ScratchPower\"":5.0}""}";
for (var i = 0; i < 10000; i++)
{
var newComponent = AnonymousClassJsonParser.MakeNewClassOrNull(jsonString);
Assert.IsTrue(newComponent is SomeCat);
}
}
[Test]
public void MakeNewComponentWithJson_ReturnNull_NotMatchClassName()
{
var jsonString = @"{""TypeName"":""blah"",""Json"":""{\""BitePower\"":10.0}""}";
var newComponent = AnonymousClassJsonParser.MakeNewClassOrNull(jsonString);
Assert.IsNull(newComponent);
}
}
/// <summary>
/// json.net 을 사용함. 객체를 래퍼로 래핑하여 타입과 json 정보를 함께 저장한다.
/// 리플렉션을 이용하여 클래스를 만든다. 따라서 클래스 타입이 어셈블리에 있다면 생성되고 없으면 실패한다.
/// 주의 : IOS에서 작동여부가 불확실하다. 테스트 필요.
/// </summary>
public class AnonymousClassJsonParser
{
public static object MakeNewClassOrNull(string nestedJson)
{
if (string.IsNullOrWhiteSpace(nestedJson))
{
return null;
}
var wrapper = JsonConvert.DeserializeObject<TypeWrapper>(nestedJson);
if (string.IsNullOrWhiteSpace(wrapper.TypeName))
{
return null;
}
try
{
var classType = Type.GetType(wrapper.TypeName, true);
return JsonConvert.DeserializeObject(wrapper.Json, classType);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
return null;
}
}
public static string MakeNestedJson(object obj)
{
var wrapper = new TypeWrapper
{
TypeName = obj.GetType().ToString(),
Json = JsonConvert.SerializeObject(obj)
};
return JsonConvert.SerializeObject(wrapper);
}
public class TypeWrapper
{
public string TypeName;
public string Json;
}
}
public class SomeDog
{
public float BitePower = 10;
}
public class SomeCat
{
public float ScratchPower = 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment