views:

572

answers:

3

I have the following classes:

public class Person
{
    public String FirstName { set; get; }
    public String LastName { set; get; }
    public Role Role { set; get; }
}

public class Role
{
    public String Description { set; get; }
    public Double Salary { set; get; }
    public Boolean HasBonus { set; get; }
}

I want to be able to automatically extract the property value diferences between Person1 and Person2, example as below:

public static List<String> DiffObjectsProperties(T a, T b)
{
    List<String> differences = new List<String>();
    foreach (var p in a.GetType().GetProperties())
    {
        var v1 = p.GetValue(a, null);
        var v2 = b.GetType().GetProperty(p.Name).GetValue(b, null);

        /* What happens if property type is a class e.g. Role???
         * How do we extract property values of Role?
         * Need to come up a better way than using .Namespace != "System"
         */
        if (!v1.GetType()
            .Namespace
            .Equals("System", StringComparison.OrdinalIgnoreCase))
            continue;

        //add values to differences List
    }

    return differences;
}

How can I extract property values of Role in Person???

A: 

If the properties aren't value types, why not just call DiffObjectProperties recursively on them and append the result to the current list? Presumably, you'd need to iterate through them and prepend the name of the property in dot-notation so that you could see what is different -- or it may be enough to know that if the list is non-empty the current properties differ.

tvanfosson
A: 

Because I don't know how to tell if:

var v1 = p.GetValue(a, null);

is String FirstName or Role Role. I have been trying to find out how to tell if v1 is a String such as FirstName or a class Role. Therefore I won't know when to recursively pass the object property (Role) back to DiffObjectsProperties to iterate its property values.

Jeffrey C
+1  A: 
public static List<String> DiffObjectsProperties(object a, object b)
{
    Type type = a.GetType();
    List<String> differences = new List<String>();
    foreach (PropertyInfo p in type.GetProperties())
    {
        object aValue = p.GetValue(a, null);
        object bValue = p.GetValue(b, null);

        if (p.PropertyType.IsPrimitive || p.PropertyType == typeof(string))
        {
            if (!aValue.Equals(bValue))
                differences.Add(
                    String.Format("{0}:{1}!={2}",p.Name, aValue, bValue)
                );
        }
        else
            differences.AddRange(DiffObjectsProperties(aValue, bValue));
    }

    return differences;
}
Diadistis
Seems to work, thank you!
Jeffrey C
Since you are passing in Objects instead of generic type T, you need to do this I think: if (a.GetType() != b.GetType()) return differences;
Jeffrey C