通用实体基类

5
我刚刚读了一篇关于通用实体基类的文章。简单来说,如果我没有理解错的话,其主要思想是将所有通用、非实体特定的字段收集到一个接口中,然后在主实体中实现它。这篇文章有点长,让我们看一些代码。
以下是基本实体接口及其通用实现的另一个接口:
public interface IEntity : IModifiableEntity
{
    object Id { get; set; }
    DateTime CreatedDate { get; set; }
    DateTime? ModifiedDate { get; set; }
    string CreatedBy { get; set; }
    string ModifiedBy { get; set; }
    byte[] Version { get; set; }
}

public interface IEntity<T> : IEntity
{
    new T Id { get; set; }
}

这是它实现为一个抽象类的例子。
public abstract class Entity<T> : IEntity<T>
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public T Id { get; set; }
    object IEntity.Id
    {
        get { return this.Id; }
    }

    public string Name { get; set; }

    private DateTime? createdDate;
    [DataType(DataType.DateTime)]
    public DateTime CreatedDate
    {
        get { return createdDate ?? DateTime.UtcNow; }
        set { createdDate = value; }
    }

    [DataType(DataType.DateTime)]
    public DateTime? ModifiedDate { get; set; }

    public string CreatedBy { get; set; }

    public string ModifiedBy { get; set; }

    [Timestamp]
    public byte[] Version { get; set; }
}

这段内容看起来非常清晰易懂,但其中有一个关于 Id 的问题。

  • 为什么 IEntity 和 IEntity 接口中都有两个不同的 Id 属性?

  • new 关键字在这里是做什么的?发生了什么?:O


1
因为一个来自非泛型接口,仅是object类型,而另一个则是特定的T类型。你需要使用new,因为它属于不同的类型,并且你希望覆盖继承声明。如果通过该接口访问实例,则Entity<T>还明确地实现了非泛型的Id - Andrew
但是所有派生自实体抽象类的具体实体都使用通用的ID属性来生成一个。所以对象ID是多余的,不是吗? - Uğur Cem Öztürk
3
如果你正在使用IEntity<T>,那么就不需要使用object Id。虽然你可以这样做,但这可能没有意义。 - Andrew
1个回答

4
为什么IEntity和IEntity<T>接口中都有两个不同的Id属性?
IEntity<T>继承自IEntity,但允许您传递要使用的特定类型的Id属性。基本接口定义IEntity将Id属性定义为对象,这不是类型安全的,如果在Entity Framework中使用,将不能转换为数据库友好的数据类型。
new关键字在那里做什么?发生了什么? :O
属性定义中的new关键字使代码更易于阅读和理解。由于IEntity<T>具有定义为隐藏基础实现IEntity.Id的属性名为Id的属性。 "new"关键字使得更容易理解IEntity<T>.Id隐藏了IEntity.Id的基础实现。
稍微深入一点
在Entity的基本抽象类的派生类中,您将提供ID属性的类型,如下所示:
public class DerivedEntity : Entity<int>
{
    public string AnotherProperty { get; set; }
}   

这告诉编译器通过Entity<T>的类型参数"T",Id属性是"int"类型的,使得在派生类中更容易使用和理解Id属性应该是什么。


1
仅供参考,这里是微软对“new”关键字的定义。所有“new”关键字所做的就是使基本实现的隐藏变得显式而不是隐式。编译器会假设您知道在隐藏属性或方法的基本版本时正在做什么,并将派生类版本取代基本实现。链接 - bman7716

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接