leora
leora

Reputation: 196469

Is there a way to make this C# comparison code more generic?

I am comparing two objects of the same type and returning the differences into a list of FieldChange objects. Right now I am listing out each field comparison like this which seems a bit suboptimal.

Is there a cleaner way of refactoring the code below to avoid the repetition? There are two sets of code below but in reality I have about 20 comparisons.

var changes = new List<FieldChange>();
if (proposedUpdatedProject.StatusId != existingProject.StatusId)
{
    var previousStatusName = existingProject.StatusShortName;
    existingProject.Status = ProjectModel.Repository.Fetch<ProjectStatus>(proposedUpdatedProject.StatusId);
    changes.Add(new FieldChange { FieldName = "Status", PreviousValue = previousStatusName, NewValue = existingProject.StatusShortName });
}

if (proposedUpdatedProject.TechOwnerId != existingProject.TechOwnerId)
{
    var previousTechOwnerName = existingProject.TechOwnerName;
    existingProject.TechOwner = ProjectModel.Repository.Fetch<Person>(proposedUpdatedProject.TechOwnerId);
    changes.Add(new FieldChange { FieldName = "Tech Owner", PreviousValue = previousTechOwnerName, NewValue = existingProject.TechOwnerName });
}   

NOTE: that all objects are derived from the same object called BaseObj. Also note that I am not just putting the values of the comparable fields into FieldChange object (id versus Name property)

Upvotes: 2

Views: 187

Answers (3)

Marcel N.
Marcel N.

Reputation: 13976

You could create a method attribute, for example called ComparableAttribute. Then you can decorate all methods in these objects with this attribute.

You can use reflection in the method you are making the comparison and iterate through all Comparable properties. The code would be much shorter (one iteration, instead of 20 if statements).

If you need custom information for certain properties, you could specify it via the ComparableAttribute attribute, as parameters.

The compare method would still take as parameters two instances, but you'll end up with a much smaller implementation. You could even cache the PropertyInfos for your types, so you don't reflect at each comparison.

Upvotes: 2

Zasz
Zasz

Reputation: 12538

Why not use INotifyPropertyChanged interface ? Look here for information on it. You simply have to implement it, and subscribe to the event. One more link

Upvotes: 0

Andyz Smith
Andyz Smith

Reputation: 708

Why not reflect into the structures:

existingProject

And compare all fields. By writing the code long-hand this way, you are adding quite a bit of information to the problem like the association between the StatusID and the StatusName, but if you choose some proper naming conventions, you could potentially automate the whole thing.

Upvotes: 0

Related Questions