.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
相关产品推荐
相关产品推荐

