Created
April 22, 2016 01:15
-
-
Save Porges/b2941573f2521b61826e90746982c61a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Reflection; | |
namespace ConsoleApplication | |
{ | |
class PropertyComparer : IEnumerable | |
{ | |
private readonly Dictionary<string, Func<object, object, bool>> _except = new Dictionary<string, Func<object, object, bool>>(); | |
private static IEnumerable<Tuple<PropertyInfo, PropertyInfo>> PropertiesInCommon(object left, object right) | |
{ | |
var leftType = left.GetType(); | |
var rightType = right.GetType(); | |
foreach (var leftProp in leftType.GetProperties()) | |
{ | |
var rightProp = rightType.GetProperty(leftProp.Name); | |
if (rightProp != null) | |
{ | |
yield return Tuple.Create(leftProp, rightProp); | |
} | |
} | |
} | |
private Func<object, object, bool> GetComparer(string name) | |
{ | |
Func<object, object, bool> result; | |
if (_except.TryGetValue(name, out result)) | |
{ | |
return result; | |
} | |
return Equals; | |
} | |
public void Add<T>(string name, Func<T, T, bool> comparer) => _except[name] = (l, r) => comparer((T) l, (T)r); | |
public void Add<T>(string name, IComparer<T> comparer) => Add<T>(name, (l, r) => comparer.Compare(l, r) == 0); | |
public bool ConsideredEqual(object left, object right) | |
{ | |
foreach (var prop in PropertiesInCommon(left, right)) | |
{ | |
var leftVal = prop.Item1.GetValue(left); | |
var rightVal = prop.Item2.GetValue(right); | |
var comparer = GetComparer(prop.Item1.Name); | |
if (!comparer(leftVal, rightVal)) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
// don't use this. it's just to convince C# to give use nice syntax | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return ((IEnumerable) _except).GetEnumerator(); | |
} | |
} | |
class Program | |
{ | |
class Cat | |
{ | |
public string Name { get; set; } | |
} | |
class Dog | |
{ | |
public string Name { get; set; } | |
} | |
static void Main(string[] args) | |
{ | |
var c = new Cat {Name = "Fido"}; | |
var d = new Dog {Name = "Fido"}; | |
var comparer = new PropertyComparer(); | |
Console.WriteLine(comparer.ConsideredEqual(c, d)); | |
d.Name = "fiDO"; | |
Console.WriteLine(comparer.ConsideredEqual(c, d)); | |
var amendedComparer = new PropertyComparer {{"Name", StringComparer.OrdinalIgnoreCase}}; | |
Console.WriteLine(amendedComparer.ConsideredEqual(c, d)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment