public static DiffResult<T, P> DiffWith<T, P>(
this IEnumerable<T> first, IEnumerable<T> second, Func<T, P> keySelector)
where T : new()
{
return new DiffResult<T, P>(first, second, keySelector);
}
public class DiffResult<T, P>
where T : new()
{
private IEnumerable<T> _first = null;
private IEnumerable<T> _second = null;
private Func<T, P> _keySelector = null;
private Lazy<P[]> _keysInFirst = null;
private Lazy<P[]> _keysInSecond = null;
private Lazy<Dictionary<P, T>> _resolvedFirst = null;
private Lazy<Dictionary<P, T>> _resolvedSecond = null;
public DiffResult(IEnumerable<T> first, IEnumerable<T> second, Func<T, P> keySelector)
{
_keySelector = keySelector;
_first = first;
_second = second;
_resolvedFirst = new Lazy<Dictionary<P, T>>(() => { return _first.ToDictionary(_keySelector, x => x); });
_resolvedSecond = new Lazy<Dictionary<P, T>>(() => { return _second.ToDictionary(_keySelector, x => x); });
_keysInFirst = new Lazy<P[]>(() => { return _resolvedFirst.Value.Keys.ToArray(); });
_keysInSecond = new Lazy<P[]>(() => { return _resolvedSecond.Value.Keys.ToArray(); });
}
public P[] KeysToAdd { get { return _keysInSecond.Value.Where(x => !_keysInFirst.Value.Contains(x)).ToArray(); } }
public P[] KeysToRemove { get { return _keysInFirst.Value.Where(x => !_keysInSecond.Value.Contains(x)).ToArray(); } }
public P[] KeysToUpdate { get { return _keysInFirst.Value.Intersect(_keysInSecond.Value).ToArray(); } }
public IEnumerable<T> ToAdd { get { return _resolvedSecond.Value.Where(x => KeysToAdd.Contains(x.Key)).Select(x => x.Value); } }
public IEnumerable<T> ToRemove { get { return _resolvedFirst.Value.Where(x => KeysToRemove.Contains(x.Key)).Select(x => x.Value); } }
public IEnumerable<T> ToUpdate { get { return _resolvedFirst.Value.Where(x => KeysToUpdate.Contains(x.Key)).Select(x => x.Value
); } }
}