I have the following method to compare DTOs.
bool Equals<T1, T2>(T1 t1, T2 t2, params Expression<Func<T1, object>>[] accessors)
{
return !(
from accessor in accessors
select ((MemberExpression) accessor.Body).Member.Name into propertyName
let p1 = typeof (T1).GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
let p2 = typeof (T2).GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
let p1val = p1.GetValue(t1, null)
let p2val = p2.GetValue(t2, null)
where !Equals(p1val, p2val)
select p1val
).Any();
}
I can call this using (a and b are instances of objects that by convention share the same properties, but that aren’t the same objects):
Equals(a, b, x => x.PropertyOne, x => x.PropertyTwo );
Which compares the the objects property by property, which is fine for most cases.
However, I found a case where I needed to compare objects that had properties of complex types and where I wanted to compare properties on the complex types instead of the objects. Something like this:
Equals(a, b, x => x.ComplexTypeProperty.ChildProp );
I have realised that I need to leave the comfy reflection comparison and enter the Expression land, but the main task here is to be able to express both a property accessor and a property accessor via a complex type property and that’s where I’m lost.
Any pointers would be nice, thanks!
The task is not so complicated:
Determine property path or expressions that are given by expressions. For instance this extension method will give you this:
Aggregate expression for second type to create function that will return value:
Now execute method that retrieve values and compare:
The good idea would be to add some caching of generated methods because compilation process is expensive.