AyCode.Core/AyCode.Core/Serializers/IIdCollectionMergeHelper.cs

95 lines
3.3 KiB
C#

using System.Collections;
using System.Runtime.CompilerServices;
using AyCode.Core.Helpers;
using static AyCode.Core.Helpers.JsonUtilities;
namespace AyCode.Core.Serializers;
/// <summary>
/// Helper class for merging IId collections during deserialization.
/// Shared between JSON and Binary deserializers.
/// </summary>
public static class IIdCollectionMergeHelper
{
/// <summary>
/// Builds a lookup dictionary from an existing IId collection.
/// Maps Id values to their corresponding items.
/// </summary>
/// <param name="existingList">The existing collection to index.</param>
/// <param name="idGetter">Function to extract Id from an item.</param>
/// <param name="idType">The type of the Id property.</param>
/// <returns>Dictionary mapping Id to item, or null if collection is empty.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Dictionary<object, object>? BuildIdLookup(
IList existingList,
Func<object, object?> idGetter,
Type idType)
{
var count = existingList.Count;
if (count == 0) return null;
var dict = new Dictionary<object, object>(count);
for (var i = 0; i < count; i++)
{
var item = existingList[i];
if (item == null) continue;
var id = idGetter(item);
if (id != null && !IsDefaultValue(id, idType))
dict[id] = item;
}
return dict;
}
/// <summary>
/// Removes orphaned items from the collection that are not present in the source IDs.
/// </summary>
/// <param name="existingList">The collection to clean up.</param>
/// <param name="existingById">Lookup dictionary of existing items.</param>
/// <param name="sourceIds">Set of IDs that were seen in source data.</param>
public static void RemoveOrphanedItems(
IList existingList,
Dictionary<object, object> existingById,
HashSet<object> sourceIds)
{
var itemsToRemove = new List<object>();
foreach (var kvp in existingById)
{
if (!sourceIds.Contains(kvp.Key))
{
itemsToRemove.Add(kvp.Value);
}
}
foreach (var item in itemsToRemove)
{
existingList.Remove(item);
}
}
/// <summary>
/// Copies properties from source object to target object using metadata.
/// </summary>
/// <typeparam name="TPropertyInfo">Type of property info (varies by serializer).</typeparam>
/// <param name="source">Source object to copy from.</param>
/// <param name="target">Target object to copy to.</param>
/// <param name="properties">Array of property accessors.</param>
/// <param name="getter">Function to get property value.</param>
/// <param name="setter">Action to set property value.</param>
public static void CopyProperties<TPropertyInfo>(
object source,
object target,
TPropertyInfo[] properties,
Func<TPropertyInfo, object, object?> getter,
Action<TPropertyInfo, object, object?> setter)
{
for (var i = 0; i < properties.Length; i++)
{
var prop = properties[i];
var value = getter(prop, source);
if (value != null)
setter(prop, target, value);
}
}
}