Search code examples
c#.net.net-coredomain-driven-design

Domain Driven Design (DDD) Common entity class with strongly typed Id


I see lots of DDD examples with something like following using Id of Guid type

    public abstract class Entity : IEquatable<Entity>
    {
        public Entity(Guid id)
        {
            Id = id;
        }
        public Guid Id { get; private init; }
    }

    public class MyDomainClass : Entity 
    {
    }

I see other set of examples not using base abstract class but using a strongly type Id which derived from generic Id class.

    public class MyDomainClass
    {
        public MyId Id { get; private set; }

        public Location(MyId id, Currency currency)
        {
            Id = id;
        }
    }
   public class Id<T> 
    {
        protected T Value { get; private set; }
        protected Id(T value)
        {
            Value = value;
        }

        public override string ToString() => Value.ToString();
        protected override object GetHashCodeComponents() => Value;
    }
   public class MyId : Id<string>
    {
        protected MyId(string value) : base(value) {
        }

    }

Can these both approaches be combined?


Solution

  • I would go with different implementation of generic Entity it is more simple and generic allows to have entities with different type of Id and comparable feature by Id, Here is an example

    public abstract class EntityWithTypedId<TId>
    {
    
        public TId Id { get; set; }
    
        protected bool Equals(EntityWithTypedId<TId> other)
        {
            return EqualityComparer<TId>.Default.Equals(Id, other.Id);
        }
    
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((EntityWithTypedId<TId>)obj);
        }
    
        public override int GetHashCode()
        {
            return EqualityComparer<TId>.Default.GetHashCode(Id);
        }
    
        public static bool operator ==(EntityWithTypedId<TId> left, EntityWithTypedId<TId> right)
        {
            return Equals(left, right);
        }
    
        public static bool operator !=(EntityWithTypedId<TId> left, EntityWithTypedId<TId> right)
        {
            return !Equals(left, right);
        }
    }
    

    and then

    public abstract class Entity : EntityWithTypedId<Guid>
    {
    
    }