Ahm*_*mad 1 c# generics inheritance
我的项目中有几个类映射到数据库中的表行。大多数类共享大量样板代码以从数据库中获取数据FetchAll,并根据给定的 id 返回某些对象/行FetchById()。
我想编写一个可以执行单一类FetchAll和FetchById(),然后我的所有其他类都可以从该对象继承。但是,我正在努力将基类定义为泛型。其他类不能继承它,同时属于与它们继承的内容相关联的泛型类型。
为了更好地解释我的问题,我将开始简化共享相似代码的两个常见类:
class Person {
   public int Id { get; set; }
   public string Name { get; set; }
   
   public static List<Person> All {
      get { /* fetch all rows and */ return List<Person>; }
   }
   public static Person FetchById(int id) {
      return All.Where(p => p.Id == id).SingleOrDefault();
   }
}
class Department {
   public int Id { get; set; }
   public string Name { get; set; }
   public string CostCenter { get; set; }
   public static List<Department> All { get { /* same logic as with Person */ } }
   public static Department FetchById(int id) { /* same logic as with Person */ }
}
现在这是我尝试做的以减少代码重复:
public interface IIdentifiable {
   // make sure all objects have an Id property
   int Id { get; set; }
}
class DbObject<T> where T: IIdentifiable {
    public static List<T> All { get {  /* return List<T>; */ } }
    public static T FetchById(int id) {
       return All.Where(object => object.Id == id).FirstOrDefault();
    }
}
现在我回到我Person和Department班级来利用DbObject:
class Person : DbObject<Person>, IIdentifiable // won't compile: The type cannot be used as type parameter T
{
    public int Id { get; set; }    
    public string Name { get; set; }
   // public static List<Person> All {get{ ... }};    // should be inherited
   // public static Person FetchById(int id) { ... }  // should be inherited
}
我对Department. 你明白了。我觉得我做错了什么。我知道它应该比这简单得多。如何同时使DbObject泛型和可继承?
您可以通过采用Curiously recurring template pattern来做到这一点。
有效地定义DbObject<T>这样T : DbObject<T>它就可以工作了。
public class DbObject<T> where T : DbObject<T>, IIdentifiable
{
    public List<T> All { get { return new List<T>(); } }
    public T FetchById(int id)
    {
        return All.Where(x => x.Id == id).FirstOrDefault();
    }
}
public class Person : DbObject<Person>, IIdentifiable
{
    public int Id { get; set; }
    public string Name { get; set; }
}
现在这段代码有效:
Person p = new Person();
List<Person> all = p.All;
在您的原始代码中,您使用的是static方法。我认为是这样你可以写List<Person> all = Person.All;,但你不能继承static方法。
您可能需要考虑创建一个负责返回人员的存储库对象。
请记住,这种方法的缺点是您需要小心。这段代码可以编译,但可能不是你想要的:
public class Department : DbObject<Person>, IIdentifiable
{
    public int Id { get; set; }
    public string Name { get; set; }
}