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

如何在泛型<T>基类中使用Linq First方法

问题:将WinUI3 MVVM主详情页的删除逻辑迁移到泛型基类

基于泛型<T>的MasterDetailViewModel<T>基类,我实现了派生类HomePageViewModel : MasterDetailViewModel<Tenant>,其中Tenant是带Id主键的数据库实体类。当前删除逻辑(RelayCommand和DeleteCommand_Executed)放在派生类中,我希望将这些代码全部移到基类中。

仅迁移RelayCommand并在基类声明抽象的DeleteCommand_Executed方法,让派生类重写的方式可以正常运行,但直接把DeleteCommand_Executed移到基类时,会出现CS1061错误:'T'未包含'Id'定义,即使指定Items.First<T>(c => c.Id == parm)也无法解决。想了解如何实现将所有删除相关代码移到基类的目标。


相关代码片段

基类声明

public abstract partial class MasterDetailViewModel<T> : ObservableObject
{
    private readonly ObservableCollection<T> items = new();
    // ... 其他代码
}

派生类声明

public partial class HomePageViewModel : MasterDetailViewModel<Tenant>
{
    // ... 其他代码
}

Tenant类定义

[Table("tenants")]
public partial class Tenant
{
    public string Email { get; set; }
    public string FirstName { get; set; }
    [Key]
    public int Id { get; set; }
    // ... 其他代码
}

派生类中原有的删除逻辑

[RelayCommand]
private void Delete(int param) // param是选中列表项的Id
{
    DeleteCommand_Executed(param);
}

private void DeleteCommand_Executed(int parm)
{
    if (parm > 0)
    {
        var toBeDeleted = Items.First(c => c.Id == parm); // 获取对应Id的记录
        DeleteItem(toBeDeleted); // 从数据库删除
    }
}

解决方案

要让泛型基类识别T的Id属性,需要通过接口约束泛型类型,具体步骤如下:

  1. 定义包含Id属性的接口
public interface IHasId
{
    int Id { get; }
}
  1. 让Tenant类实现该接口
[Table("tenants")]
public partial class Tenant : IHasId
{
    public string Email { get; set; }
    public string FirstName { get; set; }
    [Key]
    public int Id { get; set; }
    // ... 其他代码
}
  1. 修改泛型基类的约束
    给基类添加泛型约束where T : IHasId,确保T一定包含Id属性,然后将删除逻辑移到基类中:
public abstract partial class MasterDetailViewModel<T> : ObservableObject where T : IHasId
{
    private readonly ObservableCollection<T> items = new();
    // ... 其他代码

    [RelayCommand]
    private void Delete(int param)
    {
        DeleteCommand_Executed(param);
    }

    private void DeleteCommand_Executed(int parm)
    {
        if (parm > 0)
        {
            var toBeDeleted = Items.First(c => c.Id == parm);
            DeleteItem(toBeDeleted);
        }
    }

    // 定义抽象方法让派生类实现具体删除逻辑
    protected abstract void DeleteItem(T item);
}
  1. 派生类简化实现
    现在HomePageViewModel只需实现DeleteItem方法,无需再重复删除命令相关逻辑:
public partial class HomePageViewModel : MasterDetailViewModel<Tenant>
{
    protected override void DeleteItem(Tenant item)
    {
        // 在这里编写具体的数据库删除逻辑
    }
}

通过以上步骤,即可解决CS1061错误,同时将所有删除相关代码迁移到泛型基类中,实现代码复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 17:48:27