namespace YY.Admin.Core.Helper;
/// MES 只读数据:远端列表与本地缓存按 Id 对比合并
public static class MesReadOnlyCacheMergeHelper
{
public sealed record MergeResult(int Added, int Updated, int Removed)
{
public bool HasChanges => Added > 0 || Updated > 0 || Removed > 0;
}
///
/// 对比远端与本地,返回合并后的列表及变更统计。
/// 内容相同则保留本地副本; 可定制变更行的合并策略(如保留本地子表)。
///
public static (List Merged, MergeResult Stats) Merge(
IReadOnlyList local,
IReadOnlyList remote,
Func getId,
Func isContentEqual,
Func clone,
Func? mergeUpdated = null)
{
var localById = new Dictionary(StringComparer.OrdinalIgnoreCase);
foreach (var item in local)
{
var id = getId(item);
if (!string.IsNullOrWhiteSpace(id))
localById[id] = item;
}
var remoteIds = new HashSet(StringComparer.OrdinalIgnoreCase);
var merged = new List(remote.Count);
int added = 0, updated = 0;
foreach (var remoteItem in remote)
{
var id = getId(remoteItem);
if (string.IsNullOrWhiteSpace(id))
{
merged.Add(clone(remoteItem));
added++;
continue;
}
remoteIds.Add(id);
if (!localById.TryGetValue(id, out var localItem))
{
merged.Add(clone(remoteItem));
added++;
}
else if (!isContentEqual(localItem, remoteItem))
{
merged.Add(mergeUpdated != null ? mergeUpdated(localItem, remoteItem) : clone(remoteItem));
updated++;
}
else
{
merged.Add(clone(localItem));
}
}
int removed = localById.Keys.Count(id => !remoteIds.Contains(id));
return (merged, new MergeResult(added, updated, removed));
}
}