2025-06-05 20:09:28 +09:00
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
|
|
|
|
namespace UVC.Data
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// DataObject 객체 컬렉션의 변경사항을 추적하는 데이터 배열 클래스
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class DataArray : List<DataObject>, IDataObject
|
|
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 이 객체가 객체 풀에 있는지 여부를 나타냅니다.
|
|
|
|
|
|
/// 중복 반환을 방지하기 위해 DataArrayPool에서 내부적으로 사용됩니다.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
internal bool IsInPool { get; set; } = false;
|
|
|
|
|
|
|
2025-06-05 20:09:28 +09:00
|
|
|
|
// 추가 된 항목 목록
|
|
|
|
|
|
protected List<DataObject> addedList = new List<DataObject>();
|
|
|
|
|
|
// 제거 된 항목 목록
|
|
|
|
|
|
protected List<DataObject> removedList = new List<DataObject>();
|
|
|
|
|
|
// 수정 된 항목 목록
|
|
|
|
|
|
protected List<DataObject> modifiedList = new List<DataObject>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 추가된 항목에 접근할 수 있는 읽기 전용 컬렉션
|
|
|
|
|
|
public ReadOnlyCollection<DataObject> AddedItems => addedList.AsReadOnly();
|
|
|
|
|
|
|
|
|
|
|
|
// 제거된 항목에 접근할 수 있는 읽기 전용 컬렉션
|
|
|
|
|
|
public ReadOnlyCollection<DataObject> RemovedItems => removedList.AsReadOnly();
|
|
|
|
|
|
|
|
|
|
|
|
// 제거된 항목에 접근할 수 있는 읽기 전용 컬렉션
|
|
|
|
|
|
public ReadOnlyCollection<DataObject> ModifiedList => modifiedList.AsReadOnly();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 기본 생성자
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public DataArray() : base()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 초기 용량을 지정하는 생성자
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="capacity">초기 용량</param>
|
|
|
|
|
|
public DataArray(int capacity) : base(capacity)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 기존 컬렉션으로부터 생성하는 생성자
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="collection">초기 항목을 포함하는 컬렉션</param>
|
|
|
|
|
|
public DataArray(IEnumerable<DataObject> collection) : base(collection)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public DataArray(string jsonString) : base()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!string.IsNullOrEmpty(jsonString))
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
JArray jArray = JArray.Parse(jsonString);
|
|
|
|
|
|
foreach (var item in jArray)
|
|
|
|
|
|
{
|
|
|
|
|
|
Add(ConvertToDataObject(item));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new ArgumentException("Invalid JSON string format.", nameof(jsonString), ex);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// JArray로부터 DataArray를 생성하는 생성자
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="jArray">JSON 배열</param>
|
|
|
|
|
|
public DataArray(JArray jArray) : base()
|
|
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
FromJArray(jArray);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public DataArray FromCapacity(int capacity)
|
|
|
|
|
|
{
|
|
|
|
|
|
Capacity = capacity;
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public DataArray FromCollection(IEnumerable<DataObject> collection)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (collection == null) return this;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in collection)
|
2025-06-05 20:09:28 +09:00
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// base.Add를 사용하여 추적 로직을 우회하고 직접 추가합니다.
|
|
|
|
|
|
base.Add(item);
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
2025-06-26 19:46:13 +09:00
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// JArray로부터 DataArray의 내용을 채웁니다.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="jArray">JSON 배열</param>
|
|
|
|
|
|
public DataArray FromJArray(JArray jArray)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (jArray == null) return this;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in jArray)
|
|
|
|
|
|
{
|
|
|
|
|
|
// base.Add를 사용하여 추적 로직을 우회하고 직접 추가합니다.
|
|
|
|
|
|
base.Add(ConvertToDataObject(item));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return this;
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// JToken을 DataObject로 변환합니다.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private DataObject ConvertToDataObject(JToken token)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (token.Type == JTokenType.Object)
|
|
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 풀에서 객체를 가져와 JObject로 초기화합니다.
|
|
|
|
|
|
var dataObject = DataObjectPool.Get();
|
|
|
|
|
|
dataObject.FromJObject((JObject)token);
|
|
|
|
|
|
return dataObject;
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// JObject가 아닌 경우, 풀에서 새 DataObject를 가져와 값을 넣어줍니다.
|
|
|
|
|
|
var dataObject = DataObjectPool.Get();
|
2025-06-05 20:09:28 +09:00
|
|
|
|
dataObject.Add("value", ConvertJTokenToObject(token));
|
|
|
|
|
|
return dataObject;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private object ConvertJTokenToObject(JToken token)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (token.Type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case JTokenType.String:
|
|
|
|
|
|
return token.ToString();
|
|
|
|
|
|
case JTokenType.Integer:
|
|
|
|
|
|
return token.ToObject<int>();
|
|
|
|
|
|
case JTokenType.Float:
|
|
|
|
|
|
return token.ToObject<float>();
|
|
|
|
|
|
case JTokenType.Boolean:
|
|
|
|
|
|
return token.ToObject<bool>();
|
|
|
|
|
|
case JTokenType.Object:
|
2025-06-26 19:46:13 +09:00
|
|
|
|
var dataObject = DataObjectPool.Get();
|
|
|
|
|
|
dataObject.FromJObject((JObject)token);
|
|
|
|
|
|
return dataObject;
|
2025-06-05 20:09:28 +09:00
|
|
|
|
case JTokenType.Array:
|
|
|
|
|
|
JArray array = (JArray)token;
|
2025-06-26 19:46:13 +09:00
|
|
|
|
var dataArray = DataArrayPool.Get();
|
|
|
|
|
|
dataArray.FromJArray(array);
|
|
|
|
|
|
return dataArray;
|
2025-06-05 20:09:28 +09:00
|
|
|
|
default:
|
|
|
|
|
|
return token.ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-06 02:17:54 +09:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 모든 아이템이 추가 된것으로 표시합니다.
|
|
|
|
|
|
/// 전체 데이터가 갱신되었을 때 사용합니다.
|
|
|
|
|
|
/// </summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
public void MarkAllAsUpdated()
|
2025-06-06 02:17:54 +09:00
|
|
|
|
{
|
|
|
|
|
|
addedList.Clear();
|
|
|
|
|
|
addedList.AddRange(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 다른 DataObject와 현재 객체를 비교하여 다른 부분만 설정합니다.
|
|
|
|
|
|
/// 변경된 키는 자동으로 추적됩니다.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="other">비교할 DataObject</param>
|
|
|
|
|
|
public void UpdateDifferent(IDataObject other)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (other == null) return;
|
2025-06-26 19:46:13 +09:00
|
|
|
|
if (!(other is DataArray otherArray)) return;
|
2025-06-06 02:17:54 +09:00
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 기존 변경 추적 목록을 초기화합니다.
|
|
|
|
|
|
ClearTrackedChanges();
|
2025-06-07 01:53:51 +09:00
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 성능 향상을 위해 ID를 키로 사용하는 사전을 생성합니다.
|
|
|
|
|
|
var thisDict = this.ToDictionary(item => item.Id);
|
|
|
|
|
|
var otherDict = otherArray.ToDictionary(item => item.Id);
|
2025-06-07 01:53:51 +09:00
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
var thisIds = new HashSet<string>(thisDict.Keys);
|
|
|
|
|
|
var otherIds = new HashSet<string>(otherDict.Keys);
|
2025-06-07 01:53:51 +09:00
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 제거된 항목 확인 (현재 배열에는 있지만 다른 배열에는 없는 항목)
|
|
|
|
|
|
foreach (var id in thisIds.Where(id => !otherIds.Contains(id)))
|
|
|
|
|
|
{
|
|
|
|
|
|
removedList.Add(thisDict[id]);
|
|
|
|
|
|
}
|
2025-06-07 01:53:51 +09:00
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 추가된 항목 확인 (다른 배열에는 있지만 현재 배열에는 없는 항목)
|
|
|
|
|
|
foreach (var id in otherIds.Where(id => !thisIds.Contains(id)))
|
|
|
|
|
|
{
|
|
|
|
|
|
addedList.Add(otherDict[id]);
|
|
|
|
|
|
}
|
2025-06-07 01:53:51 +09:00
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 수정된 항목 확인 (양쪽 모두에 있지만 내용이 다른 항목)
|
|
|
|
|
|
foreach (var id in thisIds.Where(id => otherIds.Contains(id)))
|
|
|
|
|
|
{
|
|
|
|
|
|
var thisItem = thisDict[id];
|
|
|
|
|
|
var otherItem = otherDict[id];
|
|
|
|
|
|
|
|
|
|
|
|
// [성능 개선] ToString() 비교는 매우 비효율적입니다.
|
|
|
|
|
|
// DataObject.UpdateDifferent를 직접 호출하여 변경 사항을 적용하고,
|
|
|
|
|
|
// UpdatedCount를 통해 실제 변경 여부를 확인합니다.
|
|
|
|
|
|
thisItem.UpdateDifferent(otherItem);
|
|
|
|
|
|
if (thisItem.UpdatedCount > 0)
|
2025-06-07 01:53:51 +09:00
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
modifiedList.Add(thisItem);
|
2025-06-06 02:17:54 +09:00
|
|
|
|
}
|
2025-06-26 19:46:13 +09:00
|
|
|
|
}
|
2025-06-07 01:53:51 +09:00
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// [성능 개선] RemoveAll과 HashSet을 사용하여 제거 작업의 효율성을 높입니다.
|
|
|
|
|
|
if (removedList.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var removedItemIds = new HashSet<string>(removedList.Select(i => i.Id));
|
|
|
|
|
|
this.RemoveAll(item => removedItemIds.Contains(item.Id));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// [성능 개선] base.AddRange를 사용하여 추적 로직을 우회하고 효율적으로 추가합니다.
|
|
|
|
|
|
if (addedList.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.AddRange(addedList);
|
2025-06-06 02:17:54 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 업데이트 된 객체를 반환합니다.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public IDataObject GetUpdatedObject()
|
|
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 풀에서 새 DataArray 인스턴스를 가져옵니다.
|
|
|
|
|
|
var clone = DataArrayPool.Get();
|
|
|
|
|
|
clone.FromCapacity(this.Count);
|
2025-06-05 20:09:28 +09:00
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 배열의 모든 DataObject를 순회하며 각각을 복제합니다.
|
|
|
|
|
|
foreach (var item in this)
|
2025-06-05 20:09:28 +09:00
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// DataObject의 Clone 메서드를 호출하여 깊은 복사를 수행하고,
|
|
|
|
|
|
// base.Add를 사용해 추적 로직 없이 직접 추가합니다.
|
|
|
|
|
|
if (item.GetUpdatedObject() is DataObject updatedObject)
|
|
|
|
|
|
{
|
|
|
|
|
|
clone.Add(updatedObject);
|
|
|
|
|
|
if (addedList.Contains(item))
|
|
|
|
|
|
{
|
|
|
|
|
|
clone.addedList.Add(updatedObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (removedList.Contains(item))
|
|
|
|
|
|
{
|
|
|
|
|
|
clone.removedList.Add(updatedObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (modifiedList.Contains(item))
|
|
|
|
|
|
{
|
|
|
|
|
|
clone.modifiedList.Add(updatedObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
return clone;
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
/// 업데이트 된 속성의 수.
|
2025-06-05 20:09:28 +09:00
|
|
|
|
/// </summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
/// <returns>업데이트된 속성의 총 개수입니다. 업데이트된 속성이 없으면 0을 반환합니다.</returns>
|
|
|
|
|
|
public int UpdatedCount { get => addedList.Count + modifiedList.Count + removedList.Count; }
|
2025-06-05 20:09:28 +09:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 컬렉션의 모든 항목을 제거합니다.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public new void Clear()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Count > 0)
|
|
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
ReturnToDataObjectPool();
|
2025-06-05 20:09:28 +09:00
|
|
|
|
base.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
/// 객체를 풀에 반환하기 전에 초기 상태로 리셋합니다.
|
2025-06-05 20:09:28 +09:00
|
|
|
|
/// </summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
public void Reset()
|
2025-06-05 20:09:28 +09:00
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 포함된 DataObject들을 먼저 풀에 반환합니다.
|
|
|
|
|
|
ReturnToDataObjectPool();
|
2025-06-05 20:09:28 +09:00
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 내부 리스트와 변경 추적 리스트를 모두 비웁니다.
|
|
|
|
|
|
base.Clear();
|
|
|
|
|
|
ClearTrackedChanges();
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-26 19:46:13 +09:00
|
|
|
|
public void ReturnToPool()
|
2025-06-05 20:09:28 +09:00
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
DataArrayPool.Return(this);
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
/// 이 DataArray에 포함된 모든 DataObject를 풀에 반환하고 리스트를 비웁니다.
|
|
|
|
|
|
/// DataArray의 사용이 끝났을 때 호출해야 합니다.
|
2025-06-05 20:09:28 +09:00
|
|
|
|
/// </summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
private void ReturnToDataObjectPool()
|
2025-06-05 20:09:28 +09:00
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
foreach (var item in this)
|
2025-06-05 20:09:28 +09:00
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
DataObjectPool.Return(item);
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 변경된 인덱스 목록을 초기화합니다.
|
|
|
|
|
|
/// </summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
public void ClearTrackedChanges()
|
2025-06-05 20:09:28 +09:00
|
|
|
|
{
|
|
|
|
|
|
addedList.Clear();
|
|
|
|
|
|
removedList.Clear();
|
|
|
|
|
|
modifiedList.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
/// 동일한 상태와 값을 가진 현재 데이터 객체의 새 인스턴스를 생성합니다.
|
2025-06-05 20:09:28 +09:00
|
|
|
|
/// </summary>
|
2025-06-26 19:46:13 +09:00
|
|
|
|
/// <remarks>복제된 객체는 원본 객체와 독립적이므로, 한 객체를 변경해도 다른 객체에는 영향을 미치지 않습니다.
|
|
|
|
|
|
///</remarks>
|
|
|
|
|
|
/// <returns>현재 객체의 복사본인 새 <see cref="IDataObject"/> 인스턴스를 반환합니다.</returns>
|
|
|
|
|
|
public IDataObject Clone()
|
2025-06-05 20:09:28 +09:00
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
// 풀에서 새 DataArray 인스턴스를 가져옵니다.
|
|
|
|
|
|
var clone = DataArrayPool.Get();
|
|
|
|
|
|
clone.FromCapacity(this.Count);
|
|
|
|
|
|
|
|
|
|
|
|
// 배열의 모든 DataObject를 순회하며 각각을 복제합니다.
|
|
|
|
|
|
foreach (var item in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
// DataObject의 Clone 메서드를 호출하여 깊은 복사를 수행하고,
|
|
|
|
|
|
// base.Add를 사용해 추적 로직 없이 직접 추가합니다.
|
|
|
|
|
|
if (item.Clone() is DataObject clonedItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
clone.Add(clonedItem);
|
|
|
|
|
|
if (addedList.Contains(item))
|
|
|
|
|
|
{
|
|
|
|
|
|
clone.addedList.Add(clonedItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (removedList.Contains(item))
|
|
|
|
|
|
{
|
|
|
|
|
|
clone.removedList.Add(clonedItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (modifiedList.Contains(item))
|
|
|
|
|
|
{
|
|
|
|
|
|
clone.modifiedList.Add(clonedItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return clone;
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// DataArray를 JArray로 변환합니다.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public JArray ToJArray()
|
|
|
|
|
|
{
|
|
|
|
|
|
JArray array = new JArray();
|
|
|
|
|
|
foreach (var item in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
array.Add(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
return array;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// DataArray를 JArray로 암시적 변환합니다.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static implicit operator JArray(DataArray dataArray)
|
|
|
|
|
|
{
|
|
|
|
|
|
return dataArray.ToJArray();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// JArray를 DataArray로 암시적 변환합니다.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static implicit operator DataArray(JArray jArray)
|
|
|
|
|
|
{
|
2025-06-26 19:46:13 +09:00
|
|
|
|
var dataArray = DataArrayPool.Get();
|
|
|
|
|
|
dataArray.FromJArray(jArray);
|
|
|
|
|
|
return dataArray;
|
2025-06-05 20:09:28 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|