You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Razor Pages页面模型中使用泛型类型?

解决方案

你遇到的编译失败是因为C#默认不支持泛型类型的逆变/协变转换,除非显式声明,以下是三种可落地的实现方案:

方案1:使用协变接口(最推荐,保留强类型特性)

首先定义带协变声明的泛型接口,把布局需要调用的所有属性、方法都定义在接口中:

// out关键字声明类型参数支持协变
public interface IFormPageModel<out TRead, out TWrite>
    where TRead : IReadEntity
    where TWrite : IWriteEntity
{
    TRead ReadModel { get; }
    TWrite WriteModel { get; }
    string FormTitle { get; }
    // 其他布局需要用到的方法声明
}

让你的泛型基类实现该接口:

public class FormPageModel<ReadEntity, WriteEntity> : IFormPageModel<ReadEntity, WriteEntity>
    where ReadEntity : class, IReadEntity, new()
    where WriteEntity : class, IWriteEntity, new()
{
    // 实现接口属性即可,原有逻辑无需修改
    public ReadEntity ReadModel { get; set; } = new();
    public WriteEntity WriteModel { get; set; } = new();
    public string FormTitle { get; set; }
}

最后修改FormLayout.cshtml的Model声明:

@model IFormPageModel<IReadEntity, IWriteEntity>

协变特性允许将IFormPageModel<具体实现类, 具体实现类>的实例自动转换为IFormPageModel<IReadEntity, IWriteEntity>类型,编译直接通过。


方案2:抽离非泛型基类(兼容性最好,适用于所有.NET版本)

把布局需要用到的公共逻辑抽离到非泛型抽象基类:

public abstract class FormPageModelBase
{
    public abstract IReadEntity ReadModel { get; }
    public abstract IWriteEntity WriteModel { get; }
    public string FormTitle { get; set; }
    // 其他布局需要的公共方法
}

让你的泛型基类继承该非泛型基类:

public class FormPageModel<ReadEntity, WriteEntity> : FormPageModelBase
    where ReadEntity : class, IReadEntity, new()
    where WriteEntity : class, IWriteEntity, new()
{
    public ReadEntity ReadModel { get; set; } = new();
    public WriteEntity WriteModel { get; set; } = new();
    // 实现基类抽象属性
    public override IReadEntity ReadModel => ReadModel;
    public override IWriteEntity WriteModel => WriteModel;
}

布局直接声明非泛型基类为Model即可:

@model FormPageModelBase

方案3:布局声明泛型参数(适用于.NET 6+,需要保留具体泛型类型的场景)

如果你的布局需要用到泛型的具体类型特性,可以直接给布局声明泛型参数,修改FormLayout.cshtml:

@typeparam TRead where TRead : class, IReadEntity, new()
@typeparam TWrite where TWrite : class, IWriteEntity, new()
@model FormPageModel<TRead, TWrite>

子页面引用该布局时会自动推断泛型类型,无需额外传参:

@page
@model FormPageModel<自定义读实体, 自定义写实体>
@{
    Layout = "FormLayout.cshtml";
}

内容的提问来源于stack exchange,提问作者Ali EXE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 04:36:08