replaysmike / anydiff Goto Github PK
View Code? Open in Web Editor NEWA CSharp (C#) diff library that allows you to diff two objects and get a list of the differences back.
License: Other
A CSharp (C#) diff library that allows you to diff two objects and get a list of the differences back.
License: Other
var diff = list1.Diff(list2, ComparisonOptions.All | ComparisonOptions.AllowCollectionsToBeOutOfOrder | ComparisonOptions.AllowEqualsOverride);
throws System.NotSupportedException pointing at IEnumerator.Reset() . I want to ignore ordering differences in lists. I tried igoring, but still getting it. Could you check this one please ? Version is 1.0.88
[IgnoreDataMember]
[JsonIgnore]
public virtual IEnumerable<string> SomeEnumerableIds
{
get { yield return this.someStringId; }
}
System.NotSupportedException: Specified method is not supported.
at ***********.****Entity.get_SomeEnumerableIds()+
System.Collections.IEnumerator.Reset()
at AnyDiff.DiffProvider.GetDifferences(String propertyName, Type propertyType, TypeConverter typeConverter, IEnumerable1 attributes, Object left, Object right, Object parent, List
1 differences, Int32 currentDepth, Int32 maxDepth, <37c2b6f9-1728-45df-bb6e-473d4690fe19>ObjectHashcodeMap objectTree, String path, ComparisonOptions options, ICollection1 propertiesToExcludeOrInclude, DiffOptions diffOptions) at AnyDiff.DiffProvider.RecurseProperties(Object left, Object right, Object parent, List
1 differences, Int32 currentDepth, Int32 maxDepth, <37c2b6f9-1728-45df-bb6e-473d4690fe19>ObjectHashcodeMap objectTree, String path, ComparisonOptions comparisonOptions, ICollection1 propertiesToExcludeOrInclude, DiffOptions diffOptions) at AnyDiff.DiffProvider.ComputeDiff[T](T left, T right, Int32 maxDepth, ComparisonOptions comparisonOptions, DiffOptions diffOptions, Expression
1[] propertiesToExcludeOrInclude)
at AnyDiff.Extensions.Extensions.Diff[T](T left, T right, Int32 maxDepth, ComparisonOptions comparisonOptions, DiffOptions diffOptions, Expression1[] propertiesToExcludeOrInclude) at AnyDiff.Extensions.Extensions.Diff[T](T left, T right, ComparisonOptions comparisonOptions, Expression
1[] propertiesToExcludeOrInclude)
System.NotSupportedException: Specified method is not supported. at Newtonsoft.Json.Linq.JProperty.JPropertyList.<GetEnumerator>d__1.System.Collections.IEnumerator.Reset() at ObjectCompare.DiffProvider.GetCountFromEnumerable(IEnumerable enumerable) at ObjectCompare.DiffProvider.GetDifferences(String propertyName, Type propertyType, TypeConverter typeConverter, Object left, Object right, Object parent, ICollection
1 differences, Int32 currentDepth, Int32 maxDepth, ObjectHashcodeMap objectTree, String path, ComparisonOptions options, ICollection1 propertyList) at ObjectCompare.DiffProvider.RecurseProperties(Object left, Object right, Object parent, ICollection
1 differences, Int32 currentDepth, Int32 maxDepth, ObjectHashcodeMap objectTree, String path, ComparisonOptions options, ICollection1 propertyList) at ObjectCompare.DiffProvider.GetDifferences(String propertyName, Type propertyType, TypeConverter typeConverter, Object left, Object right, Object parent, ICollection
1 differences, Int32 currentDepth, Int32 maxDepth, ObjectHashcodeMap objectTree, String path, ComparisonOptions options, ICollection1 propertyList) at ObjectCompare.DiffProvider.RecurseProperties(Object left, Object right, Object parent, ICollection
1 differences, Int32 currentDepth, Int32 maxDepth, ObjectHashcodeMap objectTree, String path, ComparisonOptions options, ICollection1 propertyList)
The issue is happening when you have different objects inherited from one parent object and we put them in the list (List) container.
private static long GetCountFromEnumerable(IEnumerable enumerable)
{
if (enumerable == null)
return 0L;
var count = 0L;
var enumerableType = enumerable.GetType().GetExtendedType(DefaultTypeSupportOptions);
if (enumerableType.IsCollection)
return ((ICollection)enumerable).Count;
if (enumerableType.IsArray)
return ((Array)enumerable).LongLength;
if (enumerableType.IsEnumerable)
{
if (enumerable is IEnumerable<Newtonsoft.Json.Linq.JToken> jPropertyList)
{
return jPropertyList.Count(); // I added this line to fix the issue
}
}
// count the enumerable
foreach (var row in enumerable)
count++;
// try to reset the enumerable, if IEnumerable implements it
var enumerator = enumerable.GetEnumerator();
try
{
enumerator.Reset();
}
catch (NotImplementedException) { }
return count;
}
How to find differences that are nested deep inside a property?
In the classes mentioned below, how do I get the differences which are listed 2 level deep e.g., Cool.Author.Address.City and Cool.Author.Address.Country
public class Cool
{
public int id;
public int revision;
public string[] vehicles;
public Author author;
public string tagline;
public Gender gender;
}
public class Author
{
public string FirstName;
public string LastName;
public Address Address;
}
public class Address
{
public string City;
public string Country;
}
Hi,
Would it be possible to have a new attribute to avoid diff? I'm using the JSON serializer and I cannot use the dedicated attribute due to this.
Thanks
What is my best option to serialize a Difference object? Should it be given a parameterless constructor? Or should I make a proxy class instead?
Is there a way to get a list of all the properties before the compare. Im not sure where the "objectIDField" is coming from. It looks like its a private field. Is there a way to not compare the privates?
Property name: ObjectID
Property type: System.String
Left 110007295: 7487b8ef-575e-45d8-9f1d-5cfe86323276
Right 110006740: f046b926-da60-4654-92e1-fb0f3b2e0b11
Property name: objectIDField
Property type: System.String
Left 110007295: 7487b8ef-575e-45d8-9f1d-5cfe86323276
Right 110006740: f046b926-da60-4654-92e1-fb0f3b2e0b11
private string objectIDField;
[XmlElement(IsNullable = true, Order = 6)]
public string ObjectID
{
get
{
return this.objectIDField;
}
set
{
this.objectIDField = value;
}
}
Hi,
Would it be possible to avoid the comparison from an Enumerable null vs empty?
Thanks
When computing deltas, nullable integers are not correctly determining the delta value.
It seems in some specific circumstance it's possible AnyDiff will recurse the properties of a collection, which shouldn't happen. It should only analyze the contents of a collection, it's possible that it needs to switch to using TypeSupport for some of that logic.
Will fix and cleanup.
Hi, let's say I have an object of type Person that is base object and has two child types: Employee and Candidate. Now when comparing Employee to Candidate type I use following overload of Diff method:
var changes = source.Diff(destination, ComparionOptions.AllowCompareDifferentObjects, IgnoreProperties.ConfigureForSimpleTypes()); ( where IgnoreProperties is just a static helper class that returns an array of properties to ignore)
I can clearly see that source.FirstName and destination.FirstName are not equal, yet changes are empty every time. Both objects inherit common properties from Person. They have their own specific properties, but that was something I didn't tested. Any thought on this?
Thanks.
Hello there, I'm comparing these two objects:
var obj1 = new Projection
{
Speakers = new [] { new Speaker { Id = 1, Name = "Fizz" } }
};
var obj2 = new Projection
{
Speakers = new [] { new Speaker { Id = 1, Name = "Buzz" } }
};
var diffs = AnyDiff.Diff(obj1, obj2);
As you can see, The Name
property of the first Speaker
in the array has a different value.
The resulting Difference
object is omitting the 0
index in the path. It's .Speakers.Name
but it should be .Speakers[0].Name
.
Without an index in the Path
, I can't really tell which of the objects in the array changed.
Thanks,
Moreno
Hi. Out of the blue, now I get exception: System.Reflection.TargetParameterCountException with message: Parameter count mismatch. The library was working fine for couple of months, but now these are thrown when comparing custom types, and collections of custom types. Nothing changed when it comes to the part that is comparing objects. I don't understand what could cause this.
output window:
Exception thrown: 'System.Reflection.TargetParameterCountException' in System.Private.CoreLib.dll
Exception thrown: 'System.Reflection.TargetParameterCountException' in TypeSupport.dll
Firstly, thanks for the great library, I've just found it yesterday and have found it very useful and configurable so far!
One use case I have that it doesn't seem to cater for however is the ability for one (or arguably both) of the objects to be diff'ed to be null
. I am using AnyDiff to identify differences between a source and target object for both insert and update operations against my data store. In the case of inserts, my 'source' object will be null
and it would be extremely useful for AnyDiff.Diff() to return an ICollection<Differences>
which includes all fields marked for comparison in the target object and their values in RightValue
and I suppose null
(or the most suitable 'empty' value given the fields data type) in LeftValue
.
I cannot see anyway of achieving this currently unless I am missing something? I've tried markiny my object for comparison as nullable via T?
in the types method call below:
ICollection<Difference> differences = AnyDiff.AnyDiff.Diff<User?>(
existingUser,
currentUser,
ComparisonOptions.All | ComparisonOptions.AllowCollectionsToBeOutOfOrder,
new string[] { "Id", "CreatedAt", "UpdatedAt" }
);
but this results in:
System.NullReferenceException: Object reference not set to an instance of an object.
Further stack trace:
System.NullReferenceException: Object reference not set to an instance of an object.
at TypeSupport.Extensions.<fd5fea14-b6d2-4046-8d81-b8115045ec3c>ObjectExtensions.GetProperties(Object obj, <4d7a44c8-b5f5-44bf-8471-f0980838d61e>PropertyOptions options)
at AnyDiff.DiffProvider.RecurseProperties(Object left, Object right, Object parent, List`1 differences, Int32 currentDepth, Int32 maxDepth, <37c2b6f9-1728-45df-bb6e-473d4690fe19>ObjectHashcodeMap objectTree, String path, ComparisonOptions comparisonOptions, ICollection`1 propertiesToExcludeOrInclude, DiffOptions diffOptions)
at AnyDiff.DiffProvider.ComputeDiff(Object left, Object right, Int32 maxDepth, ComparisonOptions comparisonOptions, DiffOptions diffOptions, String[] propertiesToExcludeOrInclude)
at AnyDiff.AnyDiff.Diff[T](T left, T right, ComparisonOptions comparisonOptions, String[] propertiesToExcludeOrInclude)
My best idea for a workaround currently would be to create additional classes with nullable and/or sane default fields e.g. BlankUser
, enabling the AllowCompareDifferentObjects
option and passing this in as my source in these scenarios.
If however, AnyDiff could allow for a null
left value however, that would be great?
I want to use AnyDiff within a project that is strong-named. When I try to, I get this exception at runtime.
System.IO.FileLoadException: Could not load file or assembly 'AnyDiff, Version=1.0.83.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required. (Exception from HRESULT: 0x80131044)
Because AnyDiff is not strong-named, I cannot use it within this project.
See a similar change made for auth0.net at auth0/auth0.net#281 and Microsoft's recommendation for publicly published .NET libraries here.
Request: A method that returns immediately, at the first encounter of difference, without any further difference checks.
bool IsDiff(ob1, obj2)
Justification: Sometimes, the app only cares about if the objects are same or not and then only write the updated full object to DB.
hi,
What is the license of the library? github shows GPL 3.0 license but nuget package is AGPL 3.0. Which one is correct?
This example will course a endless loop on private properties of Type.
Is this intended behavior? How do I fix this.
class TypeReference
{
private Type _type;
public string AssemblyQualifiedName { get; set; }
public Type GetTypeInt() => _type;
public TypeReference(Type type)
{
_type = type;
AssemblyQualifiedName = type.AssemblyQualifiedName;
}
}
class StaticValueProvider
{
public TypeReference Source { get; set; }
public object Value { get; set; }
}
var staticValueProvider = new StaticValueProvider()
{
Source = new TypeReference(typeof(string)),
Value = "wa"
};
var staticValueProvider2 = new StaticValueProvider()
{
Source = new TypeReference(typeof(string)),
Value = "wa"
};
var differences1 = staticValueProvider.Diff(staticValueProvider2);
If I do this comparison it works, but fields can be public.
var differences1 = staticValueProvider.Diff(staticValueProvider2,
ComparisonOptions.ExcludeList |
ComparisonOptions.CompareCollections |
// ComparisonOptions.CompareFields |
ComparisonOptions.CompareProperties);
In my example case, I am talking to a FinTech gRPC API and trying to validate that post-save security response I get back from the vendor is the same as the response I get from fetching the latest version. For some reason, I had to add ComparisonOptions.AllowCompareDifferentObjects
even though the top-level objects are the same gRPC object. I'm assuming that somewhere in my sub-graph, I have a polymorphic collection that contains a different sub-type, .e.g.
message Value {
oneof oneOfValue {
string stringValue = 1;
bool boolValue = 2;
int32 intValue = 3;
int64 longValue = 4;
double doubleValue = 5;
CustomTypedValue customTypedValue = 6;
}
}
Below is my example code - it has been running for at least 8 minutes just to compare one relatively tiny object graph, on .NET Framework 4.8.2. - Maybe the issue here is with slow reflection on an older framework, but I was not expecting it to be this slow.
var comparisonResult = AnyDiff.AnyDiff.Diff(savedSecurity, latestSecurity, ComparisonOptions.CompareProperties | ComparisonOptions.CompareCollections | ComparisonOptions.AllowCompareDifferentObjects);
I'm using AnyDiff to compare instances of the type Microsoft.TeamFoundation.Build.WebApi.BuildDefinition
from assembly Microsoft.TeamFoundation.Build2.WebApi (Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
. In certain cases (I could not really understand why), the process breaks by a System.NotSupportedException
:
System.NotSupportedException: Specified method is not supported.
at System.Reflection.TypeInfo.<get_DeclaredNestedTypes>d__23.System.Collections.IEnumerator.Reset()
at AnyDiff.DiffProvider.GetCountFromEnumerable(IEnumerable enumerable)
at AnyDiff.DiffProvider.GetDifferences(String propertyName, Type propertyType, TypeConverter typeConverter, Object left, Object right, Object parent, ICollection``1 differences, Int32 currentDepth, Int32 maxDepth, ObjectHashcodeMap objectTree, String path, ComparisonOptions options, ICollection``1 propertyList, DiffOptions diffOptions)
at AnyDiff.DiffProvider.RecurseProperties(Object left, Object right, Object parent, ICollection``1 differences, Int32 currentDepth, Int32 maxDepth, ObjectHashcodeMap objectTree, String path, ComparisonOptions comparisonOptions, ICollection``1 propertyList, DiffOptions diffOptions)
at AnyDiff.DiffProvider.GetDifferences(String propertyName, Type propertyType, TypeConverter typeConverter, Object left, Object right, Object parent, ICollection``1 differences, Int32 currentDepth, Int32 maxDepth, ObjectHashcodeMap objectTree, String path, ComparisonOptions options, ICollection``1 propertyList, DiffOptions diffOptions)
at AnyDiff.DiffProvider.RecurseProperties(Object left, Object right, Object parent, ICollection``1 differences, Int32 currentDepth, Int32 maxDepth, ObjectHashcodeMap objectTree, String path, ComparisonOptions comparisonOptions, ICollection``1 propertyList, DiffOptions diffOptions)
...
I suggest to add a try/catch block to explain the path
causing the not expected behavior, so that one can add it to the list of exceptions.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.