C#泛型IRepositoryBase<T>如何按条件返回多类型仓储实例
C#泛型仓储多类型返回实现方案
问题根因
C# 不支持开放式泛型类型(即代码中写的IRepositoryBase<>)作为方法返回值,也不存在原生联合类型语法可以同时声明多个不同封闭泛型类型为返回值。本质上IRepositoryBase<Class1>和IRepositoryBase<Class2>是两个完全独立的类型,没有共同的父级类型可以作为统一返回值,所以会编译不通过。
另外贴出的实现代码里有两处明显笔误,需要先修正:
- 两个子仓储实现类都错误继承了
RepositoryBase<Students>,应该分别对应RepositoryBase<Class1>、RepositoryBase<Class2> - 子接口名拼写不一致:定义的是
IClass1Repository/IClass2Repository,实现类里写的是IClasse1Repository/IClasse2Repository,会导致依赖注入无法解析服务
可落地方案
根据使用场景选以下任意一种即可:
方案1:新增非泛型基础仓储接口(生产环境推荐)
这是仓储模式的标准实现方式,给所有泛型仓储抽象一个非泛型的根接口,作为统一返回类型:
- 调整基础接口定义,让泛型接口继承非泛型根接口
// 非泛型根接口,所有仓储的公共父类型 public interface IRepositoryBase { // 可在此定义不需要明确实体类型的公共方法 } public interface IRepositoryBase<T> : IRepositoryBase where T : class { void Add(T obj); }
- 修改
GetRepository方法返回值为非泛型的IRepositoryBase即可正常编译:
private IRepositoryBase GetRepository(string a) { var scope = _serviceScopeFactory.CreateScope(); return a switch { "class1" => scope.ServiceProvider.GetRequiredService<IClass1Repository>(), "class2" => scope.ServiceProvider.GetRequiredService<IClass2Repository>(), _ => null }; }
后续如果需要通过非泛型接口调用公共方法,直接在IRepositoryBase中定义对应签名,在RepositoryBase<T>中实现即可。
方案2:泛型方法实现(类型安全度最高)
如果调用方可以明确自己需要的仓储对应的实体类型,直接去掉字符串参数,用泛型方法实现,完全不需要类型转换:
private IRepositoryBase<T> GetRepository<T>() where T : class { var scope = _serviceScopeFactory.CreateScope(); return scope.ServiceProvider.GetRequiredService<IRepositoryBase<T>>(); } // 调用示例 var class1Repo = GetRepository<Class1>(); class1Repo.Add(new Class1());
方案3:返回object类型(临时场景使用)
如果只是临时写简单逻辑,不想调整接口定义,直接把返回值改为object,使用时通过模式匹配强转即可:
private object GetRepository(string a) { var scope = _serviceScopeFactory.CreateScope(); return a switch { "class1" => scope.ServiceProvider.GetService<IClass1Repository>(), "class2" => scope.ServiceProvider.GetService<IClass2Repository>(), _ => null }; } // 调用示例 var repo = GetRepository("class1"); if (repo is IClass1Repository class1Repo) { class1Repo.Add(new Class1()); }
内容的提问来源于stack exchange,提问作者Stack
相关产品推荐
相关产品推荐

