Skip to content

z0isch/ObjectDiffer

 
 

Repository files navigation

NuGet version

ObjectDiffer

A class library for performing a diff of any 2 objects of the same type.

You need to use an instance of IDiffer to perform the diff. The easiest way to get an instance of IDiffer is by using the DifferFactory:

var factory = new DifferFactory();
var differ = factory.GetDefault();

If you are using ninject, you can also load the ObjectDifferModule module:

var kernel = new StandardKernel(new ObjectDifferModule());
// you can now inject an IDiffer into your classes, or get an instance directly:
var differ = kernel.Get<IDiffer>();

IDiffer has only one method, Diff<T>(T newObj, T oldObj). This returns a Difference object, or null if there is no difference. Difference has a property ChildDiffs which is a list of Difference objects representing the changes to child properties. It also contains the PropertyName ("self" for the top level object, and "Item" for items in an array), the NewValue and the OldValue.

The Difference class has a method called Filter, which returns a Difference with only the child differences that meet the provided predicate. If the parent Difference does not pass the filter, null is returned.

Notes

  1. The differ can diff arrays in 2 different ways, either by looking at the element at each index in the array, or by the equality of objects in the array. You can determine which strategy to use in either the DifferFactory or the ObjectDifferModule:
bool diffByIndex = true;

// using factory
var factory = new DifferFactory();
var differ = factory.GetDefault(diffByIndex);

// using ninject
var kernel = new StandardKernel(new ObjectDifferModule(diffByIndex));
differ = kernel.Get<IDiffer>();
  1. When the differ is diffing an array by object equality, it needs a way to determine which elements represent the same object in each list. For example:
class MyObj
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public void DiffAList(){
  var differ = kernel.Get<IDiffer>();
  
  var obj1 = new MyObj{Id = 1, Name = "object"};
  var obj2 = new MyObj{Id = 1337, Name = "another object"};

  var oldList = new List<MyObj>{obj1, obj2};
  var newList = new List<MyObj>{obj2, obj1}; //note that they are added in reverse order

  var diff = differ.Diff(newList, oldList);
  // we would expect the diff to be null, since the elements in the list are the same
  // however, if the differ just compares the objects at each index of the array, it would think we have changed both elements
}

To solve this problem, the differ assumes that if the hash code of the objects are equal, as determined by the Object.Equals method, they are supposed to be the same object. So in the example above, we would just add a Equals method to MyObj:

class MyObj
{
    public int Id { get; set; }
    public string Name { get; set; }
    
	public bool Equals(object x, object y)
	{
		return ((MyObj) x).Id == ((MyObj) y).Id;
	}
}

If you would like to employ a different strategy for determining equality, you can override the equality comparer that the differ uses like so:

// you have an IEqualityComparer called comparer that you would like to use
kernel.Rebind<IEqualityComparer<object>>().ToConstant(comparer).Named("SameObjectComparer");

About

Diffs any 2 objects of the same type

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%