0

I have method that walks through a class and checks if 2 objects has the same values.

private bool LoopThroughObjects<T>(T ob1, T ob2)
{
    Type type = ob1.GetType();
    System.Reflection.PropertyInfo[] props = type.GetProperties();

    foreach (var prop in props)
    {
        object ent1value = prop.GetValue(ob1, new object[] { });
        object ent2value = prop.GetValue(ob2, new object[] { });

        //If object is in the same namespace it's a nested element
        if(IsSameNameSpace(type.Namespace, prop.PropertyType.Namespace))
        {
            _depth++;
            ValidateEntity_AttributesNotSame(ent1value, ent2value);
        }
        else
            ComparerOutput.Add(_conjunction + prop.Name, ent1value.Equals(ent2value));

        if (BreakOnUnequally)
            if (!ent1value.Equals(ent2value))
                return false;
    }
    return true;
}

A example of an object that I can send:

public class RefelctionTestEntity
{
    public int Id { get; set; }
    public String Firstname { get; set; }
    public String Lastname { get; set; }
    public int Age { get; set; }
    public RefelctionTestEntity Child { get; set;}
    public Vehicle.Bikes Bike { get; set; }
}

I walk recursively through the object so I will also check the Child en the Bike. My question is what's the best methode to check these inner objects? What I do at this moment is check the namespace of the object against the parent namespace of the inner object:

private bool IsSameNameSpace(String baseNamespace, String propertyNamespace)
{
    if (String.IsNullOrEmpty(baseNamespace) || String.IsNullOrEmpty(propertyNamespace))
        return true;

    if (String.IsNullOrEmpty(baseNamespace) || String.IsNullOrEmpty(propertyNamespace))
        return false;

    String[] part = propertyNamespace.Split('.');
    return part[0].Equals(baseNamespace);
}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Cageman
  • 513
  • 3
  • 22
  • What do you mean by a "nested element"? It's not really clear what semantics you're trying to impose via namespaces, but it may well not be appropriate... – Jon Skeet Aug 25 '15 at 08:14
  • 2
    First you should check whether `obj1` and `obj2` are of the same type. Your code fails if `obj1` is a subtype of `obj2` and introduces a new property. Changing `obj1.GetType()` to `typeof(T)` will solve that problem. Why do you need to test for the namespace? Use `Type.IsValueType` and if it's not call this method recursively. – Sebastian Schumann Aug 25 '15 at 08:16
  • Agree with @Verarind, however it is more complex problem - you also have to keep track of properties you have already compared; otherwise you'll end in endless recursion - if you'll have var foo = new RefelctionTestEntity(); foo.Child = foo; you're in trouble. Look at http://stackoverflow.com/questions/6276439/how-to-compare-complex-objects-as-structures-in-c-sharp-for-unit-tests – Ondrej Svejdar Aug 25 '15 at 08:25
  • @Verarind The check you gave is already be done, but in another method that calls this method. I check the namespace to see if the object (Child or Bike) are inner objects. Type.IsValueType is always false. – Cageman Aug 25 '15 at 08:27
  • @Cageman all return types of your properties are of reference types? Wow. You did `GetValue(obj1, null)`. The recursive call should be done for `ent1Value` and `ent2Value`. – Sebastian Schumann Aug 25 '15 at 08:31

1 Answers1

0
//If object is in the same namespace it's a nested element

Using such a rule could quickly become a problem in future.

It would be much more convenient if you flag the recursive item property with an interface and check whether the current property implements that interface. If so just go one level deeper.

Otherwise check if the values of the property you are currently looking at match for both objects.

var interf = Text.GetType().GetInterface("MyInterface",false);

Another approach would be to use an attribute over the item to flag it.

The check for attribute would look like this :

 var att = Text.GetType().GetCustomAttributes(typeof(RecursiveTypeAttribute),false);

I wouldn't check if the current property is a reference type since you could easily introduce a reference type property in the future.

Christo S. Christov
  • 2,268
  • 3
  • 32
  • 57