using System; using System.Collections.Generic; using System.Reflection; using Abp.Extensions; namespace Abp.Domain.Entities { /// /// A shortcut of for most used primary key type (). /// [Serializable] public abstract class Entity : Entity, IEntity { } /// /// Basic implementation of IEntity interface. /// An entity can inherit this class of directly implement to IEntity interface. /// /// Type of the primary key of the entity [Serializable] public abstract class Entity : IEntity { /// /// Unique identifier for this entity. /// public virtual TPrimaryKey Id { get; set; } /// /// Checks if this entity is transient (it has not an Id). /// /// True, if this entity is transient public virtual bool IsTransient() { if (EqualityComparer.Default.Equals(Id, default(TPrimaryKey))) { return true; } //Workaround for EF Core since it sets int/long to min value when attaching to dbcontext if (typeof(TPrimaryKey) == typeof(int)) { return Convert.ToInt32(Id) <= 0; } if (typeof(TPrimaryKey) == typeof(long)) { return Convert.ToInt64(Id) <= 0; } return false; } /// public override bool Equals(object obj) { if (obj == null || !(obj is Entity)) { return false; } //Same instances must be considered as equal if (ReferenceEquals(this, obj)) { return true; } //Transient objects are not considered as equal var other = (Entity)obj; if (IsTransient() && other.IsTransient()) { return false; } //Must have a IS-A relation of types or must be same type var typeOfThis = GetType(); var typeOfOther = other.GetType(); if (!typeOfThis.GetTypeInfo().IsAssignableFrom(typeOfOther) && !typeOfOther.GetTypeInfo().IsAssignableFrom(typeOfThis)) { return false; } if (this is IMayHaveTenant && other is IMayHaveTenant && this.As().TenantId != other.As().TenantId) { return false; } if (this is IMustHaveTenant && other is IMustHaveTenant && this.As().TenantId != other.As().TenantId) { return false; } return Id.Equals(other.Id); } /// public override int GetHashCode() { if (Id == null) { return 0; } return Id.GetHashCode(); } /// public static bool operator ==(Entity left, Entity right) { if (Equals(left, null)) { return Equals(right, null); } return left.Equals(right); } /// public static bool operator !=(Entity left, Entity right) { return !(left == right); } /// public override string ToString() { return $"[{GetType().Name} {Id}]"; } } }