Skip to content

Instantly share code, notes, and snippets.

@Porges
Created April 22, 2016 01:15
Show Gist options
  • Save Porges/b2941573f2521b61826e90746982c61a to your computer and use it in GitHub Desktop.
Save Porges/b2941573f2521b61826e90746982c61a to your computer and use it in GitHub Desktop.
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