Skip to content

Instantly share code, notes, and snippets.

@glenndierckx
Last active May 8, 2025 08:10
Show Gist options
  • Save glenndierckx/53a22f54ab76ccfb79ad to your computer and use it in GitHub Desktop.
Save glenndierckx/53a22f54ab76ccfb79ad to your computer and use it in GitHub Desktop.
namespace Shared.Helpers;
public static class MergeHelper
{
public static void Merge<TCurrent, TToBe, TId>(
this IEnumerable<TCurrent> current,
IEnumerable<TToBe> toBe,
Func<TCurrent, TId> currentIdSelector,
Func<TToBe, TId> toBeIdSelector,
Action<TToBe>? onAdd = null,
Action<TCurrent, TToBe>? onUpdate = null,
Action<TCurrent>? onRemove = null)
{
var currentList = current.ToList();
var toBeList = toBe.ToList();
var leftOuterJoin = currentList.GroupJoin(toBeList, currentIdSelector, toBeIdSelector,
(currentEntity, toBeEntity) => new
{
currentEntity = (TCurrent?)currentEntity,
toBeEntity = toBeEntity.DefaultIfEmpty().SingleOrDefault()
});
var rightOuterJoin = toBeList.GroupJoin(currentList, toBeIdSelector, currentIdSelector,
(toBeEntity, currentEntity) => new
{
currentEntity = currentEntity.DefaultIfEmpty().SingleOrDefault(),
toBeEntity = (TToBe?)toBeEntity
});
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin).ToArray();
foreach (var entity in fullOuterJoin)
{
if (entity.toBeEntity is null && entity.currentEntity is not null)
{
onRemove?.Invoke(entity.currentEntity);
}
else if (entity.currentEntity is null && entity.toBeEntity is not null)
{
onAdd?.Invoke(entity.toBeEntity);
}
else if (entity.currentEntity is not null && entity.toBeEntity is not null)
{
onUpdate?.Invoke(entity.currentEntity, entity.toBeEntity);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment