ValeraT1982 / ObjectsComparer

C# Framework provides mechanism to compare complex objects, allows to override comparison rules for specific properties and types.
MIT License
352 stars 86 forks source link

Compare list and track add, update and delete. Group differences #18

Closed S9yN37 closed 4 years ago

S9yN37 commented 4 years ago

Compare list and track add, update and delete using ComparableEnumerablesComparer and IComparableEnumerableItem. Custom member names and group diferences.

Comparison Settings GroupNameAttribute Attribute type used to groups differences

MemberCustomNameAttribute Attribute type used to define custom names for properties

ValeraT1982 commented 4 years ago

Hi @S9yN37. Thank you for your work making this pull request. There are some issues I see here.

  1. I see 2 very different changes in this pull request: compare lists by content and custom names for objects and members. I think this changes need to be implemented/documented separately. See comments bellow regarding each of this change.

Compare lists by content I've already been thinking about adding this feature. But people may want to compare lists very differently. Objects has keys and order doesn't matter, Objects has keys and order matters, no specific key but all combination of all members is a key (think about list of points on the surface with x and y properties) and again sometimes order matter and sometimes doesn't.

  1. I see this feature only as set of comparers to override default behavior rather than adding it to core functionality. Your implementation covers the only one specific case (compare objects with keys without paying attention to the order).
  2. From what I've heard from people using this framework: majority of the people compare 3d party classes or classes they don't want to change to enable some features of the comparer. It couples classes with the comparer. If rather then using IComparableEnumerableItem you add lambda as a parameter to your comparer it will make solution more flexible. If you want to have something like IComparableEnumerableItem in your code then just add lambda e => e.Key to the constructor. This implementation covers much more usecases.

Custom names for objects and members

  1. Group is very generic word. It's not clear what it means.
  2. Overriding member names can be confusing because now it is used to build path to the property.
  3. Using attributes limits using of this feature only to comparing your classes.

Can you please tell a bit more about your usecase?

I really appreciate your work.

S9yN37 commented 4 years ago

Hi @ValeraT1982, I want to implement history changes for Reservations (hotel, flight, transfers...). See attached image. Mock Objects are very large and I wanted to easily compare content by implementing IComparableEnumerableItem in each item. With group, I wanted to split differences in sections as there are rendered in the UI. Propery custom name, to overwirte the defatult name of the propery. Please see example 5. And in the end I wanted to turn the differences into an history object (section, field, action, old, new). I couldn't figure out how to do all of this with the default functionality, especially part with sections and property names. Thank you for the reply and congratulations on the project, impressive work.

ValeraT1982 commented 4 years ago

@S9yN37, to accomplish this you can implement converter PathToNameConverter. As far as you have path to the property and the type of the root object you can read attributes of the property(to read custom name) and attributes of the class (section name).

Example: path: ReservationDetails.Rooms[1].Type

  1. Read MemberInfo of ReservationDetails
  2. Read MemberInfo of Rooms and extract index (probably 1 and 2 should be loop o recursion), get Section from Rooms class
  3. Read MemberInfo of Type, get CustomName attribute.
S9yN37 commented 4 years ago

Thank you