我有以下最小的、可重复的示例:
public class BaseEntity{}
public class BaseChildClass: BaseEntity{}
public class ChildA : BaseChildClass {}
public class ChildB : BaseChildClass {}
public interface IRepository<TEntity> where TEntity : BaseEntity{}
public class DataRepository<TEntity> : IRepository<TEntity>
where TEntity : BaseEntity{}
public class Program
{
public static void Main()
{
var services = new ServiceCollection();
if (ChildAFeature) // loaded from config
{
services.AddScoped<IRepository<BaseChildClass>, DataRepository<ChildA>>();
}
else
{
services.AddScoped<IRepository<BaseChildClass>, DataRepository<ChildB>>();
}
var provider = services.BuildServiceProvider();
var service = provider.GetService<BaseChildClass>();
Console.WriteLine(service.GetType());
}
}
问题是当尝试像这样注入服务时:
services.AddScoped<IRepository<BaseChildClass>, DataRepository<ChildA>>();
编译错误显示
没有从DataRepository
来IRepository
我需要根据特性标志注入ChildA
或ChildB
到存储库。所以基本上,有时我需要childda repo,有时根据条件需要childdb repo。
您的服务注册方式错误。
更新了你的。net提琴提琴链接。
这是注册泛型依赖的方法。
public static void Main()
{
var services = new ServiceCollection();
services.AddScoped(typeof(IRepository<>), typeof(DataRepository<>));
services.AddScoped<BaseChildClass, ChildA>();
var provider = services.BuildServiceProvider();
var repo = provider.GetService<IRepository<ChildA>>();
Console.WriteLine(repo.GetType());
var service = provider.GetService<BaseChildClass>();
Console.WriteLine(service.GetType());
}
泛型形参不能真正用于继承。
然而,你可以在接口中将T声明为<out T>
,那么你的用例应该可以工作。然而,这确实迫使您只使用T作为返回值,而不是作为输入值。您可以看看IEnumerable<T>
是如何声明的,它也是这样做的。