Snippets

Hakan Lindestaf Map objects from source to target

Created by Hakan Lindestaf last modified
using System;
using System.Collections.Generic;
using System.Linq;

namespace DataAccess
{
    public static class Util
    {
        public static void MapManyToManyAssociation<T>(
            ICollection<T> currentData,
            ICollection<T> newData,
            Func<T, T, bool> equality,
            Action<T> insert,
            Action<T> delete)
        {
            foreach (var existing in currentData.ToList())
            {
                var anyMatch = newData.Any(a => equality(existing, a));

                if (!anyMatch)
                    // Remove item
                    delete(existing);
            }

            foreach (var newItem in newData)
            {
                var anyMatch = currentData.Any(a => equality(newItem, a));

                if (!anyMatch)
                    insert(newItem);
            }
        }

        /// <summary>
        /// Map the new data to the existing. Changes are handled as a delete/insert.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="currentData"></param>
        /// <param name="newData"></param>
        /// <param name="equality"></param>
        /// <param name="insert"></param>
        /// <param name="delete"></param>
        /// <param name="update"></param>
        public static void MapImmutableOneToMany<TCurrent, TNew>(
            ICollection<TCurrent> currentData,
            ICollection<TNew> newData,
            Func<TCurrent, TNew, bool> equality,
            Action<TNew> insert,
            Action<TCurrent> delete,
            Action<TCurrent, TNew> update = null)
        {
            var currentItemsToRemove = new List<TCurrent>();
            var newDataList = newData?.ToList() ?? new List<TNew>();

            foreach (var current in currentData.ToList())
            {
                var matchingNewEntry = newDataList.FirstOrDefault(a => equality(current, a));

                if (matchingNewEntry != null)
                {
                    newDataList.Remove(matchingNewEntry);
                    if (update != null)
                        update(current, matchingNewEntry);
                }
                else
                    delete(current);
            }

            // Insert new
            newDataList.ForEach(a => insert(a));
        }

        /// <summary>
        /// Map objects based on position in the lists
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="currentData"></param>
        /// <param name="newData"></param>
        /// <param name="assignment"></param>
        /// <param name="insert"></param>
        /// <param name="delete"></param>
        public static void SequentialOneToManyMap<T>(
            ICollection<T> currentData,
            ICollection<T> newData,
            Action<T, T> assignment,
            Action<T> insert,
            Action<T> delete)
        {
            var currentDataArray = currentData.ToArray();
            var newDataArray = newData.ToArray();

            for (int i = 0; i < currentData.Count; i++)
            {
                if (i < newData.Count)
                    // Replace
                    assignment(currentDataArray[i], newDataArray[i]);
            }

            if (currentData.Count < newData.Count)
            {
                // Insert new items
                newDataArray.Skip(currentData.Count).ToList().ForEach(a => insert(a));
            }
            else if (currentData.Count > newData.Count)
            {
                // Delete items
                currentData.Skip(newData.Count).ToList().ForEach(a => delete(a));
            }
        }
    }
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.