Abp-Entity
看下源码:
namespace Abp.Domain.Entities { /// <summary> /// A shortcut of <see cref="Entity{TPrimaryKey}"/> for most used primary key type (<see cref="int"/>). /// </summary> [Serializable] public abstract class Entity : Entity<int>, IEntity { } /// <summary> /// Basic implementation of IEntity interface. /// An entity can inherit this class of directly implement to IEntity interface. /// </summary> /// <typeparam name="TPrimaryKey">Type of the primary key of the entity</typeparam> [Serializable] public abstract class Entity<TPrimaryKey> : IEntity<TPrimaryKey> { /// <summary> /// Unique identifier for this entity. /// </summary> public virtual TPrimaryKey Id { get; set; } /// <summary> /// Checks if this entity is transient (it has not an Id). /// </summary> /// <returns>True, if this entity is transient</returns> public virtual bool IsTransient() { if (EqualityComparer<TPrimaryKey>.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; } /// <inheritdoc/> public virtual bool EntityEquals(object obj) { if (obj == null || !(obj is Entity<TPrimaryKey>)) { 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<TPrimaryKey>)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<IMayHaveTenant>().TenantId != other.As<IMayHaveTenant>().TenantId) { return false; } if (this is IMustHaveTenant && other is IMustHaveTenant && this.As<IMustHaveTenant>().TenantId != other.As<IMustHaveTenant>().TenantId) { return false; } return Id.Equals(other.Id); } public override string ToString() { return $"[{GetType().Name} {Id}]"; } } }
提供了主键Id,主键类型可以自定义。
关于EqualityComparer,netstandard类中,也就是.net core中。
#region 程序集 netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51 // C:\Users\MaiBenBen\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll #endregion namespace System.Collections.Generic { // // 摘要: // Provides a base class for implementations of the System.Collections.Generic.IEqualityComparer`1 // generic interface. // // 类型参数: // T: // The type of objects to compare. public abstract class EqualityComparer<T> : IEqualityComparer<T>, IEqualityComparer { // // 摘要: // Initializes a new instance of the System.Collections.Generic.EqualityComparer`1 // class. protected EqualityComparer(); // // 摘要: // Returns a default equality comparer for the type specified by the generic argument. // // 返回结果: // The default instance of the System.Collections.Generic.EqualityComparer`1 class // for type T. public static EqualityComparer<T> Default { get; } // // 摘要: // When overridden in a derived class, determines whether two objects of type T // are equal. // 在派生类中重写时,确定两个类型为T的对象
//规格相同
// 参数: // x: // The first object to compare. // // y: // The second object to compare. // // 返回结果: // true if the specified objects are equal; otherwise, false. public abstract bool Equals(T x, T y); // // 摘要: // When overridden in a derived class, serves as a hash function for the specified // object for hashing algorithms and data structures, such as a hash table. // // 参数: // obj: // The object for which to get a hash code. // // 返回结果: // A hash code for the specified object. // // 异常: // T:System.ArgumentNullException: // The type of obj is a reference type and obj is null. public abstract int GetHashCode(T obj); } }