1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | using System; using System.Collections.Generic; using System.Diagnostics; using Newtonsoft.Json; using NUnit.Framework; using Zenject; namespace Assembly_CSharpTests.PDCTest.Native { /// /// ๊ฐ์ฒด๋ค์ ์น ๋ค๊ณ ์๋ ๊ฐ์ฒด ์ ์ฅ์. ๊ฐ์ฒด ์์ฑ์์ ์ธ ID๋ ๋ค๊ณ ์์. /// internal class ObjectContainer { public int CurrentManId; public int CurrentWeaponId; public List<Man> ManList = new List<Man>(); public List<Weapon> WeaponList = new List<Weapon>(); } internal interface ISaveIDHas { int ID { get; } } internal class Man : ISaveIDHas { [Inject] private ObjectContainer _objectContainer; public string Name; public int WeaponId; public int ID { get; set; } [JsonIgnore] public Weapon Weapon => _objectContainer.WeaponList[WeaponId]; //์ฅ๋นํ ๋ ์๋ก์ ID๋ฅผ ์ค์ ํด์ค๋ค. //๋ฌด๊ธฐ ์
์ฅ์์๋ ์ฃผ์ธ์ ์ ๋ณด๋ง ์ ์ฅํจ.(์ํ๋์ง ์๊ฒ) public void Equip(Weapon gunForMan) { WeaponId = gunForMan.ID; Weapon.Equipped(this); } public int GetDamage() { return Weapon.Damage; } public class Factory : Factory<Man> { public Man CreateWithID(ObjectContainer container) { var newMan = Create(); newMan.ID = container.CurrentManId; container.ManList.Add(newMan); container.CurrentManId++; return newMan; } } } internal class Weapon : ISaveIDHas { [Inject] private ObjectContainer _objectContainer; public int Damage; public int OwnerManId; public int ID { get; set; } [JsonIgnore] public Man Owner => _objectContainer.ManList[OwnerManId]; public void Equipped(Man man) { OwnerManId = man.ID; } public class Factory : Factory<Weapon> { public Weapon CreateWithID(ObjectContainer container) { var newWeapon = Create(); newWeapon.ID = container.CurrentWeaponId; container.WeaponList.Add(newWeapon); container.CurrentWeaponId++; return newWeapon; } } } internal class Test_ReferenceSaveLoad : ZenjectUnitTestFixture { [Inject] public Man.Factory MansFactory; [Inject] public Weapon.Factory WeaponFactory; [Inject] private ObjectContainer _objectContainer; [SetUp] public void Install() { Container.Bind<ObjectContainer>().AsSingle(); Container.BindFactory<Man, Man.Factory>().FromNew(); Container.BindFactory<Weapon, Weapon.Factory>().FromNew(); Container.Inject(this); } [Test] public void Test_Performance_ListGetByIndex_VS_GetField() { //๋ง์๋ดค์ 1๋ง๊ฐ ๋ ์ผ๋ ์ ์์ง... int length = 10000; for (int i = 0; i < length; i++) { WeaponFactory.CreateWithID(_objectContainer); } Console.WriteLine($"{_objectContainer.WeaponList.Count}"); //๋ฆฌ์คํธ์์ ๊บผ๋ด์ค๊ธฐ(๋์ ์ฐธ์กฐ)์ ๋ถํ์ธก์ //O(1) ์ด๋ฏ๋ก ๋๋ฆด ์ด์ ๊ฐ ์๋ค. var stopwatch = new Stopwatch(); stopwatch.Start(); for (int i = 0; i < length; i++) { var found = _objectContainer.WeaponList[i]; } stopwatch.Stop(); Console.WriteLine($"using List index {length} loops, {stopwatch.ElapsedMilliseconds}ms!"); //๋ฏธ๋ฆฌ ์ฐพ์๋๊ธฐ (๋ณดํต ํ๋๋ณ์ ์ฌ์ฉ)์์ ๋ถํ์ธก์ //ํ๋๋ง๋์ง๋ง... stopwatch.Reset(); stopwatch.Start(); var freeFound = _objectContainer.WeaponList[1]; for (int i = 0; i < length; i++) { var found = freeFound; } stopwatch.Stop(); Console.WriteLine($"using freeFound, {length} loops, {stopwatch.ElapsedMilliseconds}ms!"); } [Test] public void Test_SaveRefID() { var dummyMan = MansFactory.CreateWithID(_objectContainer); //์์ด๋๊ฐ 0์ธ ์ฌ๋ var tomeMan = MansFactory.CreateWithID(_objectContainer); //์์ด๋๊ฐ 1์ธ ์ฌ๋ var dummyGun = WeaponFactory.CreateWithID(_objectContainer); //์์ด๋๊ฐ0์ธ ๋ฌด๊ธฐ var goodGun = WeaponFactory.CreateWithID(_objectContainer); //์์ด๋๊ฐ1์ธ ๋ฌด๊ธฐ goodGun.Damage = 10; //์ด์ ๋ค๋ ค์ค๋ค.์ฐธ์กฐ์ฐ๊ฒฐ (๋ก๋ํ ๋๋ ํ์ํ์ง ์์) (๊ทธ๋ฌ๋ ๊ทธ๋ํฝ ๋ณ๊ฒฝ๋ฑ์ ํ๊ฒ ๋ค๋ฉด ํ์ํ ์ ์์ง) tomeMan.Equip(goodGun); tomeMan.Name = "Tome"; //์ธ์ด๋ธ ํ๋ก์ธ์ค var json = JsonConvert.SerializeObject(_objectContainer); Console.WriteLine(json); //๋ก๋ํ๋ก์ธ์ค _objectContainer = JsonConvert.DeserializeObject<ObjectContainer>(json, new JsonSerializerSettings { ContractResolver = new ZenjectContractResolver(Container) }); //๋ก๋๋ ์ค๋ธ์ ํธ ์ ์ฅ์์ ๊ฐ์ฒด ๊ฐ์ ํ์ธ. Assert.AreEqual(2, _objectContainer.ManList.Count); Assert.AreEqual(2, _objectContainer.WeaponList.Count); //์ฌ๋์ ํ๋ ๊บผ๋ด ๊ฐ์ฒด ๋ณต๊ฐ ์ํ์ ๋งํฌ๋ฅผ ํ์ธํ๋ค. var loadedTome = _objectContainer.ManList[1]; Assert.AreEqual(1, loadedTome.Weapon.ID); Assert.AreEqual("Tome", loadedTome.Name); Assert.AreEqual(10, loadedTome.GetDamage()); //๋ฌด๊ธฐ๋ ์ฃผ์ธ์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์์. Assert.AreEqual(loadedTome.ID, loadedTome.Weapon.Owner.ID); } } } | cs |
์ ์ ํธ +Json.net + ์ฐธ์กฐ์ ์ฅ ์ฑ๊ณต.
ID๋ฅผ ํตํ ํต์ง ์ธ์ด๋ธ ๋ก๋ ์ฑ๊ณตํ๋ค.
์ ์ฅ๋๋ ๊ฐ์ฒด๋ค์ ์ ๋ถ ์ ์ฅ์์ ๋ฆฌ์คํธ์ ID ๋ก ๊ด๋ฆฌ๋๊ณ ,
๋ค๋ฅธ ๊ฐ์ฒด์ ๊ด๊ณ๋ฅผ ๋งบ์ ๋ (์ฐธ์กฐ๋ฅผ ๋ธ๋)๋ ID๋ง ๋ฐ๋ก ์ ์ฅํ๋ ์.
์ฌ์ฉ๋ฒ : ์ฌ์
๋ณดํต
Man.Weapon = gun;
์ด๋ผ๊ณ ์ธ ๊ฒ์
Man.WeaponId = gun.Id;
๋ก ์จ์ฃผ๋ ๊ฒ์ผ๋ก ๋.
์ฐธ์กฐ๊ฐ์ฒด๋ฅผ ๋ถ๋ฌ์ธ ๋๋ ์ค์๊ฐ์ผ๋ก (=>) ์ ์ฅ์์์ ID๋ก ์ฐพ์์.
์ฑ๋ฅ : ๋ฌธ์ ์์.
์ ์ฅ์์ List์์ index ๋ก ๋ถ๋ฌ ์ฐ๋ ๊ฒ์ด๋ฏ๋ก, ๋ถํ๋ ํ๋์ ์ฐธ์กฐ ๋ฐ๋๋๊ฑฐ๋ ์ฐจ์ด ์์.
(C# list๋ ๋ด๋ถ๊ฐ ๋ฐฐ์ด์ด๋ผ์ ์งฑ๋น ๋ฆ)
(์๋์ฐจ์ด๊ฐ ๋ ์๊ฐ ์์ง...)
์ธ์ด๋ธ/๋ก๋ ์ฉ์ด์ฑ : ์์ฃผ์ฌ์
์ธ์ด๋ธ ํ ๋๋ ๊ฑ ObjectStorage๋ง ํต์งธ๋ก ์๋ฆฌ์ผ/๋์๋ฆฌ์ผ ํด์ฃผ๋ฉด ๋.
๋ณต๊ฐ๋ ๊ฐ์ฒด๋ค์ ๋ค๋ฅธ ๊ฐ์ฒด๋ค์ ID๋ฅผ ๋น์ฐํ ๋ค๊ณ ์์.(int๋๊น!) ๊ทธ๋์ ์ธ์ ๋ ๋์ ์ผ๋ก ์ฐธ์กฐ๋ฅผ ์ฐพ์ ์ฐ๋ฉด ๋จ.
{
"CurrentManId":2,"
CurrentWeaponId":2,"
ManList":[{"Name":null,"WeaponId":0,"ID":0},{"Name":"Tome","WeaponId":1,"ID":1}],
"WeaponList":[{"Damage":0,"OwnerManId":0,"ID":0},{"Damage":10,"OwnerManId":1,"ID":1}]
}
๊ฐ๋! ์ด ๊น๋ํ Json์ ๋ณด๋ผ! ์ด๋ ๊ฒ ๊น๋ํ Json๋ณธ๊ฒ ์ผ๋ง ๋ง์ด๋๊ฐ!
(๊ทผ๋ฐ ๋์ค์๋ ๋ฐ์ด๋๋ฆฌ๋ก ๋ฐ๊ฟ์๊ฐ์. json ๊ฒ๋ ๋ฌด๊ฒ๊ณ ์...)
๋จ์ : ๊ฐ์ฒด๋ฅผ ์ฒ์ ์์ฑํ ๋ ๋ฌธ๋ฒ์ด ์ด์ง ๊น๋ค๋ก์. ๊ทธ๋ ๋ค๊ณ ObjectStorage ์๊ฒ ์์ฑ๊ถํ์ ์ค์๋ ์ฑ
์์์ฌ ๋ฌธ์ ๊ฐ ์๊น.
์ํฐํจํด ๋์๊ฐ ์ด์ง ๋์ง๋ง
ObjectStorage์ ์ฑ ์์ ์ต๋ํ ์ ๊ฒ ์ง์ธ๋ ค๊ณ ๋ ธ๋ ฅํ๋ฉด ๋์ง ์์๊น.
ID๋ก ์ ์ฅํ๋ค๋ ์์ด๋์ด ๋ด ์ค ๊ฒ์ด์ผ ๋ณต ๋ง์ด ๋ฐ์.
๋ก๋ ๋น์ฒจ๋ ๊ฑฐ์ผ!
์ธ๊ฒ๊ฐค์ ๋ณด๋ฐฐ
๊ตฟ์ด๋ค
๋ท๋ถ์ธ๋ฐ ์ด๋ฒ 2019.3 ๋ฒ์ [SerializeReference] ์ดํธ๋ฆฌ๋ทฐํธ ์ฐ๋ฉด ๊ฐ๋จํ๊ฒ ๋ ๋ฏ