如何正确声明相关泛型基类的未来子类类型的返回类型

本文关键字:未来 子类 类型 返回类型 基类 泛型 何正确 声明 | 更新日期: 2023-09-27 18:04:36

有人试图在ASP中实现抽象。. NET MVC和c#。

它们有一个基本实体控制器,它应该为它的派生类(实体)做大部分的工作。其中,他们有一个有问题的方法,该方法应该返回每个表的数据库上下文(他们没有使用任何像EF这样的DB框架)。方法如下:

protected abstract DbContext<EntityViewModel> CreateContext();

所以,假设他们有一个Category表,这个方法应该被实现:

protected override DbContext<EntityViewModel> CreateContext()
{
    return new CategoryDbContext();
}

但是c#说他们不能隐式地转换它,等等…

下面是上下文类:

public abstract class DbContext<T>
{
    public abstract void Create(T entity);
    public abstract List<T> Read(ModifyData data);
    public abstract void Update(T entity);
    public abstract void Delete(T entity);
}
public class CategoryDbContext : DbContext<CategoryViewModel>
{
    public override void Create(CategoryViewModel entity)
    {
    }
    public override List<CategoryViewModel> Read(ModifyData data)
    {
    }
    public override void Update(CategoryViewModel entity)
    {
    }
    public override void Delete(CategoryViewModel entity)
    {
    }
}

在这个设计中有什么问题,如何改变这些类来工作?

如何正确声明相关泛型基类的未来子类类型的返回类型

将基本实体控制器类修改为如下内容:

public abstract class BaseEntityController<TDbContext, TEntityViewModel>
    where TDbContext : DbContext<TEntityViewModel>
    where TEntityViewModel : EntityViewModel
{
    protected abstract TDbContext CreateContext();
}

然后创建BaseEntityController的子类如下:

public class CategoryController : BaseEntityController<CategoryDbContext, CategoryViewModel>
{
    protected abstract TDbContext CreateContext();
}

然后创建DbContext的子类

public class CategoryDbContext : DbContext<CategoryViewModel>
{
    public override void Create(CategoryViewModel entity)
    {
    }
    public override List<CategoryViewModel> Read(ModifyData data)
    {
    }
    public override void Update(CategoryViewModel entity)
    {
    }
    public override void Delete(CategoryViewModel entity)
    {
    }
}

通过向BaseEntityController类添加DbContext本身子类形式的泛型类型参数,我们能够返回占位符而不是DbContext的基本泛型形式,从而避免了强制类型转换问题,并使代码更具强类型。

作为奖励,我们可以重构上面的代码,使用一些泛型嵌套类(参数/泛型命名空间)技术来DRY泛型类型参数声明本身。例如:

public abstract class Entity<TEntity, TDbContext, TViewModel>
    where TEntity : Entity<TEntity, TDbContext, TEntityViewModel>
    where TDbContext : Entity<TEntity, TDbContext, TEntityViewModel>.BaseDbContext, new()
    where TViewModel : Entity<TEntity, TDbContext, TEntityViewModel>.BaseViewModel
{
    public class EntityController
    {
        protected TDbContext CreateContext() { return new TDbContext(); }
    }
    public abstract class BaseDbContext
    {
        public abstract void Create(TViewModel entity);
        public abstract List<TViewModel> Read(ModifyData data);
        public abstract void Update(TViewModel entity);
        public abstract void Delete(TViewModel entity);
    }
    public abstract class BaseViewModel {}
}

然后子类(子命名空间?)泛型命名空间及其成员如下:

public class Category : Entity<Category, Category.DbContext, Category.ViewModel>
{
    pubic class DbContext : BaseDbContext
    {
        public override void Create(CategoryViewModel entity)
        {
        }
        public override List<ViewModel> Read(ModifyData data)
        {
        }
        public override void Update(CategoryViewModel entity)
        {
        }
        public override void Delete(CategoryViewModel entity)
        {
        }
    }
    pubic class ViewModel : BaseViewModel
    {
    }
}

请注意,没有进一步的需求表明,我们已经能够消除对EntityController子类化的需要。但是,如果我们需要子类化它,我们可以将EntityController更改为BaseEntityController,并可选择为其子类形式添加一个泛型类型参数到实体的"泛型命名空间",以防我们需要在基代码中使用或返回未来的子类类型。