andrew4582

Comparer Utility with Example

Mar 3rd, 2013
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.05 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. namespace ConsoleApplication1
  6. {
  7.     /// <summary>
  8.     /// Utility class for comparing complex objects
  9.     /// </summary>
  10.     public static class ComparerUtil
  11.     {
  12.         public static DifferencesResult<T> GetDifferences<T, TKey>(
  13.             IEnumerable<T> originalList,
  14.             IEnumerable<T> changedList,
  15.             Func<T, TKey> keyExtractor)
  16.         {
  17.  
  18.             DifferencesResult<T> results = new DifferencesResult<T>();
  19.  
  20.             var keyComparer = new KeyEqualityComparer<T, TKey>(keyExtractor);
  21.  
  22.             results.Added = changedList.Except(originalList, keyComparer);
  23.             results.Removed = originalList.Except(changedList, keyComparer);
  24.  
  25.             return results;
  26.         }
  27.  
  28.         public static DifferencesResult<T> GetDifferences<T, TKey, TDiff>(
  29.            IEnumerable<T> originalList,
  30.             IEnumerable<T> changedList,
  31.             Func<T, TKey> keyExtractor,
  32.             Func<T, TDiff> differenceExtractor)
  33.         {
  34.  
  35.             DifferencesResult<T> results = new DifferencesResult<T>();
  36.  
  37.             var keyComparer = new KeyEqualityComparer<T, TKey>(keyExtractor);
  38.             var diffComparer = new KeyEqualityComparer<T, TDiff>(differenceExtractor);
  39.  
  40.             results.Added = changedList.Except(originalList, keyComparer);
  41.             results.Removed = originalList.Except(changedList, keyComparer);
  42.             results.Changed = changedList.Except(originalList, diffComparer)
  43.                                         .Except(results.Added, keyComparer)
  44.                                         .Except(results.Removed, keyComparer);
  45.  
  46.             return results;
  47.         }
  48.  
  49.         public class DifferencesResult<T>
  50.         {
  51.             public IEnumerable<T> Added { get; set; }
  52.             public IEnumerable<T> Removed { get; set; }
  53.             public IEnumerable<T> Changed { get; set; }
  54.             public DifferencesResult()
  55.             {
  56.                 Added = new T[0];
  57.                 Removed = new T[0];
  58.                 Changed = new T[0];
  59.             }
  60.         }
  61.  
  62.         /// <summary>
  63.         /// Generice impl of <see cref="IEqualityComparer"/>
  64.         /// </summary>
  65.         /// <example>
  66.         /// var treeComparer = new KeyEqualityComparer<TreeDefinition, int?>((t) => t.TreeID);
  67.         /// </example>
  68.         /// <typeparam name="T">The type of object comparing</typeparam>
  69.         /// <typeparam name="TKey">The type of key comparing</typeparam>
  70.         class KeyEqualityComparer<T, TKey> : IEqualityComparer<T>
  71.         {
  72.             protected readonly Func<T, TKey> keyExtractor;
  73.  
  74.             public KeyEqualityComparer(Func<T, TKey> keyExtractor)
  75.             {
  76.                 this.keyExtractor = keyExtractor;
  77.             }
  78.  
  79.             public virtual bool Equals(T x, T y)
  80.             {
  81.                 return this.keyExtractor(x).Equals(this.keyExtractor(y));
  82.             }
  83.  
  84.             public int GetHashCode(T obj)
  85.             {
  86.                 return this.keyExtractor(obj).GetHashCode();
  87.             }
  88.         }
  89.     }
  90.      
  91.     public class ComparerUtilExample
  92.     {
  93.         static void Main(string[] args)
  94.         {
  95.             var list = (new String[] { "Hello", "World", "Apple" })
  96.                 .Select((t, i) => new Entity(i + 1, t)).ToList();
  97.  
  98.             var list2 = (new String[] { "Hello", "World", "Apple" })
  99.                 .Select((t, i) => new Entity(i + 1, t)).ToList();
  100.  
  101.             list2.RemoveAt(0);
  102.             list2.Add(new Entity(10, "Orange"));
  103.             list2[0].Name += " Changed";
  104.  
  105.             //returns what has been added and removed by comparing keys
  106.             var diffs = ComparerUtil.GetDifferences<Entity, int>(list, list2, (k) => k.Id);
  107.             WriteChanged<Entity>(list, list2, diffs);
  108.  
  109.             //returns what has been added, removed, and changed by comparing by key func and value func
  110.             var diffsWChanged = ComparerUtil.GetDifferences<Entity, int, string>(list, list2, (k) => k.Id, (v) => v.Name);
  111.             WriteChanged<Entity>(list, list2, diffsWChanged);
  112.  
  113.         }
  114.  
  115.         class Entity
  116.         {
  117.             public int Id { get; set; }
  118.             public string Name { get; set; }
  119.             public Entity(int id, string name)
  120.             {
  121.                 Id = id;
  122.                 Name = name;
  123.             }
  124.  
  125.             public override string ToString()
  126.             {
  127.                 return string.Format("{0}:{1}", Id, Name);
  128.             }
  129.         }
  130.  
  131.         private static void WriteChanged<T>(List<T> list, List<T> list2, ComparerUtil.DifferencesResult<T> diffs)
  132.         {
  133.             Console.WriteLine("list: " + string.Join(" | ", list));
  134.             Console.WriteLine("list: " + string.Join(" | ", list2));
  135.  
  136.             Console.WriteLine("Added:   " + string.Join(" | ", diffs.Added));
  137.             Console.WriteLine("Removed: " + string.Join(" | ", diffs.Removed));
  138.             Console.WriteLine("Changed: " + string.Join(" | ", diffs.Changed));
  139.             Console.WriteLine();
  140.         }
  141.     }
  142. }
Advertisement
Add Comment
Please, Sign In to add comment