继承具有不同泛型参数的通用接口

3

我不确定这是不是我没有使用正确语法或者我缺少某个概念。

所以基本的设计如下:

public abstract class ListItemModelBase
{
    Guid id { get; set; }
}

public abstract class ListModelBase<T> where T : ListItemModelBase
{
    List<T> Items { get; set; }
}

public class OrderListModel : ListModelBase<OrderListItemModel>
{
}

这一切都很顺利,但现在我想为我的MVC项目中使用的控制器添加一些继承关系。
因此,我想要做的是:
public interface IListController<T> where T : ListModelBase<ListItemModelBase>
{
    T GetList(int Page, int ItemsPerPage);
}

那么,我可以这样做:

public class OrderListController : IListController<OrderListModel>, BaseController
{
    public OrderListModel GetList(int Page, int ItemsPerPage)
    {

    }
}

但显然由于需要为 ListModelBase 应用泛型类型,这是不可能的。
这里的目标是使我能够使用 IListController 接口来表示我可以假定 controller.GetList(1, 10) 将向我返回一个 ListModelBase,然后我可以随后假定返回的模型将在列表部分的每个项目上都有一个 Id。
这是可能的吗?还是有更好的方法可以实现我想要做的事情吗?
更新:
为了明确,我知道我可以在控制器级别定义多个类型,但那不是我想要的。
所以我知道我可以这样做:
public interface IListController<T, TItemModel> 
      where T : ListModelBase<TListModel>
      where TItemModel : ListItemModelBase
{
    T GetList(int Page, int ItemsPerPage);
}

你发布的代码有什么问题?在我这里编译得很好(当我添加一个扩展ListItemModelBase的虚拟OrderListItemModel时)。包括“我想要做的是…”下面的部分。我不太清楚你在问什么。 - TypeIA
你们能否提供一个示例,说明在这种情况下如何使用协变性? - Martin
2
@dvnrrs List<T> 不是协变的。没有办法获得具有 Add 方法的协变、强类型集合。 - MarcinJuraszek
所以没有办法做我想要的事情吗? - Martin
@Martin:我认为如果你需要某些东西,而其他地方无法获得,那么你应该考虑自己制作。List<T>无法胜任的事实并不意味着你不能创建一个变体列表。 - Magus
显示剩余4条评论
1个回答

0
放宽对IListController的限制,可以采用以下方式(如果可以使用较低级别的类型,如IEnumerable,则不要在接口上公开List):
public abstract class ListItemModelBase
{
    public Guid Id { get; set; }
}

public class ListItem : ListItemModelBase
{
}

public abstract class ListModelBase<T> where T : ListItemModelBase
{
    public IEnumerable<T> Items { get; set; }
}

public class OrderListModel : ListModelBase<ListItem>
{
}

public interface IListController<T>
{
    T GetList(int page, int itemsPerPage);
}

public abstract class BaseController
{
}

public class OrderListController : BaseController, IListController<OrderListModel>
{
    public OrderListModel GetList(int page, int itemsPerPage)
    {
        return new OrderListModel();
    }
}

然后你可以这样做:

var controller = new OrderListController();
var orderListModel = controller.GetList(0, 10);
foreach (var kindOfA in orderListModel.Items)
{
    doSomeThing(kindOfA.Id);
}

那么,没有办法将IListController限制为仅限于ListModelBase吗? - Martin
当然,像where T : ListModelBase<ListItemModelBase>这样的吗?我认为这个问题中混淆的根源是因为命名不好。如果你整理一下你的类/接口名称,并按照这个答案的大纲进行操作,你就会没问题的。对于我可能造成的任何困惑,我表示抱歉。 - mhoff

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