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

.NET 8中按特定条件筛选ApplicationDbContext的DbSet属性

实现GetApplicationDbContextDbSets方法的解决方案

以下是针对需求实现的完整代码,通过反射精准筛选符合所有条件的PropertyInfo列表:

using System.Reflection;
using Microsoft.EntityFrameworkCore;

public static class DbContextExtensions
{
    public static IEnumerable<PropertyInfo> GetApplicationDbContextDbSets(this ApplicationDbContext context)
    {
        var dbSetGenericDef = typeof(DbSet<>);
        var iEntityGenericDef = typeof(IEntity<>);

        return context.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
            // 匹配条件1:实例、公开、虚拟属性,且具备公开的get/set方法
            .Where(prop => prop.IsVirtual 
                           && prop.GetGetMethod() != null 
                           && prop.GetSetMethod() != null)
            .Where(prop =>
            {
                // 跳过非泛型类型
                if (!prop.PropertyType.IsGenericType)
                    return false;

                // 匹配条件2:属性类型继承自DbSet<>泛型定义
                var propGenericDef = prop.PropertyType.GetGenericTypeDefinition();
                if (!propGenericDef.Equals(dbSetGenericDef))
                    return false;

                // 匹配条件3:DbSet仅含一个泛型参数
                var dbSetGenericArgs = prop.PropertyType.GetGenericArguments();
                if (dbSetGenericArgs.Length != 1)
                    return false;

                var innerGenericType = dbSetGenericArgs[0];
                // 匹配条件4:泛型参数是IEntity<>的实例,且仅含一个嵌套泛型参数TEntity
                if (!innerGenericType.IsGenericType 
                    || innerGenericType.GetGenericTypeDefinition() != iEntityGenericDef 
                    || innerGenericType.GetGenericArguments().Length != 1)
                    return false;

                var tEntityType = innerGenericType.GetGenericArguments()[0];
                // 匹配条件5:TEntity满足IEntity<TEntity>的泛型约束
                var iEntityConstraints = iEntityGenericDef.GetGenericArguments()[0].GetGenericParameterConstraints();
                return iEntityConstraints.All(constraint => constraint.IsAssignableFrom(tEntityType));
            });
    }
}

核心逻辑拆解

  • 条件1验证:通过BindingFlags过滤范围,结合IsVirtual和方法存在性检查确保属性符合要求。
  • 条件2-3验证:先判断属性类型是否为DbSet<>的泛型实例,再确认泛型参数数量为1。
  • 条件4验证:检查DbSet的泛型参数是否是IEntity<>的实例,且仅包含一个嵌套泛型参数。
  • 条件5验证:提取IEntity<>的泛型约束规则,验证TEntity是否全部满足。

使用示例

using (var dbContext = new ApplicationDbContext())
{
    var validDbSets = dbContext.GetApplicationDbContextDbSets();
    foreach (var prop in validDbSets)
    {
        Console.WriteLine($"匹配的DbSet属性:{prop.Name},类型:{prop.PropertyType.FullName}");
    }
}

注:如果你的IEntity<T>有自定义泛型约束(如where T : class, IEntity<T>),代码会自动适配这些约束,无需额外修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:57:48