C#如何动态将类类型传递给泛型Repository类完成数据库操作
实现方案
该需求可实现,C# 支持运行时动态构造泛型类型并调用对应方法,以下是两种可直接运行的实现方案:
方案1:反射调用(无需修改现有仓储结构)
适合不想调整现有静态泛型仓储定义的场景,直接通过反射构造泛型类型、调用Add方法。
基础代码对齐你的现有实现:
// 修正你原接口的笔误 public interface IRepository<TEntity> where TEntity : class { Task Add(TEntity entity); } // 你现有使用的静态泛型仓储 public static class Repository<TEntity> where TEntity : class { // 模拟Add方法实现,你可以替换成自己的数据库操作逻辑 public static Task Add(TEntity entity) { var nameProp = typeof(TEntity).GetProperty("Name"); Console.WriteLine($"已添加{typeof(TEntity).Name}对象,Name值:{nameProp?.GetValue(entity)}"); return Task.CompletedTask; } } // 你的业务模型类 public class UserClass { public string Name { get; set; } } public class DepartmentClass { public string Name { get; set; } } public class CategoryClass { public string Name { get; set; } }
动态调用代码:
string condition = "1"; // 替换为你的实际条件 Type entityType; object entityInstance; // 根据条件匹配类型、构造对应实例 switch (condition) { case "1": entityType = typeof(UserClass); entityInstance = new UserClass { Name = "John" }; break; case "2": entityType = typeof(DepartmentClass); entityInstance = new DepartmentClass { Name = "研发部" }; break; case "3": entityType = typeof(CategoryClass); entityInstance = new CategoryClass { Name = "数码分类" }; break; default: throw new ArgumentOutOfRangeException(nameof(condition), "不支持的条件值"); } // 动态构造泛型仓储类型,获取Add方法 var genericRepoType = typeof(Repository<>).MakeGenericType(entityType); var addMethod = genericRepoType.GetMethod("Add", new[] { entityType }); // 执行异步调用 await (Task)addMethod.Invoke(null, new[] { entityInstance });
方案2:非泛型接口重载(性能更高)
适合可以调整现有仓储结构的场景,通过新增非泛型接口避免高频反射开销。
调整后的仓储定义:
// 新增非泛型仓储接口 public interface IRepository { Task Add(object entity); } // 泛型仓储实现非泛型接口 public class Repository<TEntity> : IRepository<TEntity>, IRepository where TEntity : class { // 原有泛型Add方法 public Task Add(TEntity entity) { Console.WriteLine($"已添加{typeof(TEntity).Name}对象,Name值:{entity.Name}"); return Task.CompletedTask; } // 显式实现非泛型Add,内部做类型转换后调用泛型方法 Task IRepository.Add(object entity) { return Add((TEntity)entity); } } // 简单工厂类,用于获取对应实体的仓储实例 public static class RepositoryFactory { public static IRepository GetRepository(Type entityType) { var repoType = typeof(Repository<>).MakeGenericType(entityType); return (IRepository)Activator.CreateInstance(repoType); } } // 业务模型类同上 public class UserClass { public string Name { get; set; } } public class DepartmentClass { public string Name { get; set; } } public class CategoryClass { public string Name { get; set; } }
调用代码:
string condition = "2"; // 替换为你的实际条件 Type entityType; object entityInstance; switch (condition) { case "1": entityType = typeof(UserClass); entityInstance = new UserClass { Name = "John" }; break; case "2": entityType = typeof(DepartmentClass); entityInstance = new DepartmentClass { Name = "研发部" }; break; case "3": entityType = typeof(CategoryClass); entityInstance = new CategoryClass { Name = "数码分类" }; break; default: throw new ArgumentOutOfRangeException(nameof(condition), "不支持的条件值"); } // 直接通过非泛型接口调用 var repo = RepositoryFactory.GetRepository(entityType); await repo.Add(entityInstance);
注意事项
- 反射方案如果用于性能敏感场景,可将构造好的
addMethod缓存到字典中,避免每次反射的开销 - 两种方案都要求传入的实体实例与匹配的类型完全对应,否则会抛出类型转换异常
- 如果你使用依赖注入容器,方案2可以直接从容器中解析对应类型的仓储实例,无需自己实现工厂逻辑
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

