Created
June 20, 2017 08:53
-
-
Save tomfanning/3999647649786a2a66964f5142709250 to your computer and use it in GitHub Desktop.
C# reflection-based object diff
This file contains 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
public class Compared | |
{ | |
public object Left { get; set; } | |
public object Right { get; set; } | |
} | |
public static System.Collections.Generic.Dictionary<string, Compared> Diff(object o1, object o2) | |
{ | |
var result = new System.Collections.Generic.Dictionary<string, Compared>(StringComparer.Ordinal); | |
if (o1.GetType() != o2.GetType()) | |
{ | |
throw new ArgumentException("Objects are not of the same type"); | |
} | |
var oType = o1.GetType(); | |
foreach (System.Reflection.PropertyInfo prop in oType.GetProperties()) | |
{ | |
object o1Value = prop.GetValue(o1); | |
object o2Value = prop.GetValue(o2); | |
#warning This only supports collections of primitives, not collections of collections. Fine for our purposes but not general purpose without further work. | |
if (prop.PropertyType != typeof(string) && typeof(System.Collections.IEnumerable).IsAssignableFrom(prop.PropertyType)) | |
{ | |
var seq1 = (System.Collections.IEnumerable)o1Value; | |
var seq2 = (System.Collections.IEnumerable)o2Value; | |
int cnt1 = seq1.Cast<object>().Count(); | |
int cnt2 = seq2.Cast<object>().Count(); | |
if (cnt1 != cnt2) | |
{ | |
result.Add(prop.Name, new Compared { Left = $"{cnt1} items", Right = $"{cnt2} items" }); | |
} | |
var enumerator1 = seq1.GetEnumerator(); | |
var enumerator2 = seq2.GetEnumerator(); | |
for (int i = 0; i < cnt1; i++) | |
{ | |
enumerator1.MoveNext(); | |
enumerator2.MoveNext(); | |
var o1eValue = enumerator1.Current; | |
var o2eValue = enumerator2.Current; | |
if (!object.Equals(o1eValue, o2eValue)) | |
{ | |
result.Add(prop.Name, new Compared { Left = $"item {i}={o1eValue}", Right = $"item {i}={o2eValue}" }); | |
} | |
} | |
} | |
else | |
{ | |
if (!object.Equals(o1Value, o2Value)) | |
{ | |
result.Add(prop.Name, new Compared { Left = o1Value, Right = o2Value }); | |
} | |
} | |
} | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment