Entities and Value Objects

One of the building blocks of a Domain Driven Design application are entities and value objects.

Entity is an object with identity, it is defined by its identity and continuity not its attributes, for example a person is an entity with identity (maybe it is social security number, maybe a user id, maybe Guid) but this person remains the same even after changing his address or even his name. two instances of person objects with the same identity are the same even if they are not the same object in memory, even if they have different attributes (Properties and Fields) thus it is a mutable type, you can change its attributes and it remains the same entitiy.

Value Object on the other hand is an object that contains attributes with no conceptual identity, two value objects with the same attributes are the same. thus it is immutable type, when you change any attribute of value object it becomes a different value object. an example of value object is address (unless your application domain states that address is a key information with identity like shipping applications), the address is a value object attached to the person, you can not identify address on its own, you just can fetch a person entity and get the address.

When developing a DDD application in .net usually I create a Layer Super Type for entities and value objects as follows:

EntityBase: Each entity should have Identity, this identity could be an int (auto number), a Guid, a string, custom identity object, or any type. this identity should be the base of object hash code, equality, and comparing operators. the following base class handles these aspects:

    public abstract class EntityBase<TEntity, TID> :
        IEquatable<EntityBase<TEntity, TID>>
        where TEntity : EntityBase<TEntity, TID>
    {
        #region Identity

        public virtual TID ID { get; protected set; }

        #endregion

        #region Overrides

        /// <summary>
        /// Indicates whether the current object
        /// is equal to another object of the same type.
        /// </summary>
        /// <returns>
        /// true if the current object is equal
        /// to the <paramref name="other"/> parameter;
        /// otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(EntityBase<TEntity, TID> other)
        {
            if (other == null)
                return false;

            // Handle the case of comparing two NEW objects
            var otherIsTransient = Equals(other.ID, default(TID));
            var currentIsTransient = Equals(ID, default(TID));

            if (otherIsTransient && currentIsTransient)
                return ReferenceEquals(other, this);

            return other.ID.Equals(ID);
        }

        /// <summary>
        /// Equality
        /// </summary>
        public override bool Equals(object obj)
        {
            var other = obj as TEntity;

            return Equals(other);
        }

        /// <summary>
        /// Get hash code
        /// </summary>
        public override int GetHashCode()
        {
            var thisIsTransient = Equals(ID, default(TID));

            // When this instance is transient, we use the base GetHashCode()
            return thisIsTransient ? base.GetHashCode() : ID.GetHashCode();
        }

        /// <summary>
        /// Equal operator
        /// </summary>
        public static bool operator ==
            (EntityBase<TEntity, TID> x, EntityBase<TEntity, TID> y)
        {
            return Equals(x, y);
        }

        /// <summary>
        /// Not equal operator
        /// </summary>
        public static bool operator !=
            (EntityBase<TEntity, TID> x, EntityBase<TEntity, TID> y)
        {
            return !(x == y);
        }

        #endregion
    }

The entity base has two generic parameters, one for the type of entity TEntity, and the other for identity type TID, it implements IEquatable .net interface.

ID field is defined in line 7 using the TID type.

Implementation of strongly typed IEquatable Equals method and Object override Equals methods are provided to handle equality of two entities given and check their transient state. transient means that the entity has been created without setting the ID yet, thus the ID have a default value based on type (if reference type will be null, if primitive type will hold the default value), of course there should not be an entity defined with an id of null or default value. if both entities are transient then we have to check if they point to the same memory address thus they are the same object in terms of .net, otherwise we shall compare the identities.

The equals and not equals operators are also implemented and the GetHashCode also should return the identity’s hash code.

ValueObjectBase: Value object have no Identity, object hash code should represent the hash code of all it’s attributes, equality, and comparing operators should compare all and each field in the object:

    public class ValueObjectBase<TValueObject> :
        IEquatable<TValueObject>
        where TValueObject : ValueObjectBase<TValueObject>
    {
        #region Overrides

        /// <summary>
        /// Indicates whether the current object
        /// is equal to another object of the same type.
        /// </summary>
        /// <returns>
        /// true if the current object is equal
        /// to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(TValueObject other)
        {
            if (other == null)
                return false;

            // Compare all public properties
            var publicProperties = GetType().GetProperties();

            if (publicProperties != null && publicProperties.Any())
                return publicProperties
                    .All(item => item.GetValue(this, null)
                    .Equals(item.GetValue(other, null)));

            return true;
        }

        /// <summary>
        /// Equality
        /// </summary>
        public override bool Equals(object obj)
        {
            // If both are null, or both are same instance, return true
            if (ReferenceEquals(obj, this))
                return true;

            if (obj == null)
                return false;

            var item = obj as ValueObjectBase<TValueObject>;

            if (item == null)
                return false;

            return Equals((TValueObject) item);
        }

        /// <summary>
        /// Get hash code
        /// </summary>
        public override int GetHashCode()
        {
            var hashCode = 31;
            var changeMultiplier = false;
            const int index = 1;

            // Compare all public properties
            var publicProperties = GetType().GetProperties();

            if (publicProperties != null && publicProperties.Any())
            {
                foreach (var value in publicProperties
                    .Select(item => item.GetValue(this, null)))
                {
                    if (value != null)
                    {
                        hashCode = hashCode * ((changeMultiplier) ? 59 : 114)
                            + value.GetHashCode();
                        changeMultiplier = !changeMultiplier;
                    }
                    else
                        hashCode = hashCode ^ (index * 13); // Support order
                }
            }

            return hashCode;
        }

        /// <summary>
        /// Equal operator
        /// </summary>
        public static bool operator ==
            (ValueObjectBase<TValueObject> x, ValueObjectBase<TValueObject> y)
        {
            return Equals(x, y);
        }

        /// <summary>
        /// Not equal operator
        /// </summary>
        public static bool operator !=
            (ValueObjectBase<TValueObject> x, ValueObjectBase<TValueObject> y)
        {
            return !(x == y);
        }

        #endregion
    }

This implementation is taken from Cesar de la Torre which uses reflection to compare all the fields of the value object.

About these ads

3 thoughts on “Entities and Value Objects

  1. Can you explain the use of IEquatable on the classes a little more? In what scenario should we compare entities or value objects? I started looking over the NLayerAppV2 on codeplex and saw similar code. Great article by the way!

  2. You utilize equality in many aspect:

    – You can check for equality deliberately in code using Equals() or == and != operators:
    [Test]
    public void Two_Entities_With_Same_ID_Are_Equals()
    {
    var entity1 = new MyEntity();
    entity1.SetID(1);
    entity1.SampleProperty = “Sample Value 2″;

    var entity2 = new MyEntity();
    entity2.SetID(1);
    entity2.SampleProperty = “Sample Value”;

    1. Assert.AreEqual(true, entity1.Equals(entity2)); // Calls IEquatable.Equals()
    2. Assert.AreEqual(true, MyEntity.Equals(entity1, entity2)); // Calls Object.Equals()
    3. Assert.AreEqual(true, entity1 == entity2);
    4. Assert.AreEqual(false, entity1 != entity2);
    }
    When you do override IEquatable.Equals() it will be called in the first Assert line.
    When you do override Object.Equals(), your overridden implementation is also called in calls to the static Equals() method on your class as in the second Assert line.
    Third and forth Assert lines will call your overridden implementation of == and != operators.

    – It is used by .Net framework class libraries specially collection classes like ArrayList, and generic collection classes like “List<>” when comparing objects, these collection classes calls Equals methods to determine if collection contains a given object, when finding objects in the list, or when removing an entity from a list, like the following test:
    [Test]
    public void Comparing_Entities_In_ArrayList()
    {
    var entity1 = new MyEntity();
    entity1.SetID(1);
    entity1.SampleProperty = “Sample Value”;

    var entity2 = new MyEntity();
    entity1.SetID(2);
    entity1.SampleProperty = “Sample Other Value”;

    var arrayList = new ArrayList {entity1, entity2};

    Assert.AreEqual(true, arrayList.Contains(entity1)); // Contains() calls Object.Equals()
    Assert.AreEqual(1, arrayList.IndexOf(entity2)); // IndexOf() calls Object.Equals()

    arrayList.Remove(entity1); // Remove() calls Object.Equals()

    Assert.AreEqual(false, arrayList.Contains(entity1));
    Assert.AreEqual(0, arrayList.IndexOf(entity2));
    }

    These calls to Contains(), IndexOf(), and Remove() calls your overriden implementation of Object.Equals().
    On the other hand, the generic collection classes like “List<>” will call the IEquitable members as described in MSDN: “The IEquatable interface is used by generic collection objects such as “Dictionary<>”, “List<>”, and “LinkedList<>” when testing for equality in such methods as Contains, IndexOf, LastIndexOf, and Remove. It should be implemented for any object that might be stored in a generic collection”.

    For more information and examples, check the following links:

    http://msdn.microsoft.com/en-us/library/ms131187.aspx

    http://msdn.microsoft.com/en-us/library/ms131190.aspx

    http://www.codeproject.com/KB/dotnet/IEquatable.aspx

  3. Pingback: [MVC 3] ObjectSet Extension Method–CountAll « My Web Anecdotes

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s