3

With lazy loading configured, I run into an issue regarding object comparison. My overriden Equals-method within each domain entity class contains the following line:

if (obj == null || !obj.GetType().Equals(GetType()))

Obviously, The type comparison will fail as obj is a proxy instance. I've already seen some NHibernate-snippets which unproxy an object and return the real instance. But as I enforce a domain driven design, I do not want any ORM-specific code within my domain layer. I also cannot unproxy the instance on caller side [e.g. foo.Equals(Unproxy(bar))] as the caller is my application layer which also doesn't contain any ORM-specific code (all NHibernate dependencies are injected by Windsor).

Long story short: is there any generic code to get the real instance?

mbue
  • 1,591
  • 2
  • 14
  • 34
  • Why do you want to get the type for the equality comparison? Doesn't your entity have a natural identity to compare on? If it's a value object you'd compare on the attributes... – MattDavey Oct 16 '12 at 11:19
  • Well but if I only compare the natural id and I got domain object types A, B and instances A a, B b and a.id = b.id, my Equals-method would return true, even if the objects are totally different. E.g. a car and a dog both with id = 1 would be considered as true. – mbue Oct 16 '12 at 11:24
  • ah, I thought you were talking about `IEquatable.Equals` - my mistake! – MattDavey Oct 16 '12 at 16:21

2 Answers2

5

The way to solve that is to do a cast:

public class Person
{
    public int Id { get; set; }

    public override bool Equals(object obj)
    {
        var person = obj as Person;

        if (person == null)
        {
            return false;
        }

        return person.Id == this.Id;
    }
}

The cast works because the proxy inherits from your class (e.g. PersonProxy : Person)

The null check is unnecessary as the as cast will just return null if obj is either null or not an object that can be cast as a person.

Trevor Pilley
  • 16,156
  • 5
  • 44
  • 60
  • Thank you, didn't expect the solution to be THAT trivial :) – mbue Oct 16 '12 at 11:33
  • 2
    @mbue Caution: This won't work with classes that are mapped with inheritance mapping. See here: http://stackoverflow.com/questions/3523686/issue-with-casting-proxies-when-using-nhibernate-table-per-subclass-inheritance – cremor Oct 16 '12 at 11:37
  • Thanks @mbue I don't use inheritance mapping so wasn't aware of that. – Trevor Pilley Oct 16 '12 at 11:45
  • Thank you @cremor, luckily I don't use inheritance mapping. ;) – mbue Oct 16 '12 at 11:56
3

Alternatively you could create a GetTypeUnproxied method like shown here: https://github.com/sharparchitecture/Sharp-Architecture/blob/master/Solutions/SharpArch.Domain/DomainModel/BaseObject.cs

This method would even work with inheritance mapping since it returns the real type of the object that is inside the proxy.

cremor
  • 6,669
  • 1
  • 29
  • 72
  • Honestly I don't understand the solution. GetTypeUnproxied seems to simply invoke GetType(). How can this solve the problem? – mbue Oct 16 '12 at 12:24
  • 1
    @mbue If you call GetTypeUnproxied() on a proxy, it forwards the call to the real method on the entity. So if you are in the GetTypeUnproxied() method, "this" is pointing to the real entity (not the proxy). Therefore GetType() then returns the type of the real entity. – cremor Oct 16 '12 at 12:47