Generic Value Object
I just wanted to share my attempt for implementing a generic base class for Value Objects, popularized by Eric Evans and the Domain-Driven Design community. I must say that I got heavily inspired by Jimmy Bogard’s implementation, which got me thinking about such an approach. Contrary to his implementation, I used static reflection instead of dynamic reflection in order to determine which fields to use for equality and string representation.
public abstract class ValueObject<T> : IEquatable<T> where T : ValueObject<T> { private List<PropertyInfo> Properties { get; set; } protected ValueObject() { Properties = new List<PropertyInfo>(); } public override Boolean Equals(Object obj) { if(ReferenceEquals(null, obj)) return false; if(obj.GetType() != GetType()) return false; return Equals(obj as T); } public Boolean Equals(T other) { if(ReferenceEquals(null, other)) return false; if(ReferenceEquals(this, other)) return true; foreach(var property in Properties) { var oneValue = property.GetValue(this, null); var otherValue = property.GetValue(other, null); if(null == oneValue || null == otherValue) return false; if(false == oneValue.Equals(otherValue)) return false; } return true; } public override Int32 GetHashCode() { var hashCode = 36; foreach(var property in Properties) { var propertyValue = property.GetValue(this, null); if(null == propertyValue) continue; hashCode = hashCode ^ propertyValue.GetHashCode(); } return hashCode; } public override String ToString() { var stringBuilder = new StringBuilder(); foreach(var property in Properties) { var propertyValue = property.GetValue(this, null); if(null == propertyValue) continue; stringBuilder.Append(propertyValue.ToString()); } return stringBuilder.ToString(); } protected void RegisterProperty( Expression<Func<T, Object>> expression) { Check.Argument(expression, "expression").IsNotNull(); MemberExpression memberExpression; if(ExpressionType.Convert == expression.Body.NodeType) { var body = (UnaryExpression)expression.Body; memberExpression = body.Operand as MemberExpression; } else { memberExpression = expression.Body as MemberExpression; } if(null == memberExpression) { var message = ResourceLoader<ValueObject<T>> .GetString("InvalidMemberExpression"); throw new InvalidOperationException(message); } Properties.Add(memberExpression.Member as PropertyInfo); } }
This generic base class takes care of the equality by overriding Equals and GetHashCode from the Object class and implementing the IEquality interface. It also takes care of a default implementation of the ToString method.
Using this base class significantly reduces the amount of code for implementing a value object in the domain.
public class Tag : ValueObject<Tag> { public String Name { get; private set; } public Tag(String name) { Name = name; RegisterProperty(value => value.Name); } }
And that is that. The only thing I’ve omitted in this example is the validation of the specified name.
I’ve been using this base class in a couple of projects now, and so far, I’ve been very pleased with the results although it can always be improved. I’d love to read your comments.






@Christian: You’re right. I don’t seem to be able to even copy a single line of code to WLW. I need a vacation.
What an incredible waste of time.