在C#的依赖注入中,通用的写法如下
services.AddScoped<ITestScopeContract, TestScopeService>();获取方法如下
var testScopeContract= provider.GetService<ITestScopeContract>();这样可以获取一个ITestScopeContract接口的实例,那么如果我们同时针对接口做多个实现,如何精准获取到对应想要的实现类?
傻瓜式的写法如下
var testScopeContracts= provider.GetServices<ITestScopeContract>();
var testScopeContract1= testScopeContracts.Where(a=>a.GetType()==typeof(service))这样确实能获取到对应其中指定的实现类,但这样写有一个弊端就是你必须同时实例化了所有实现了ITestScopeContract这个接口的对象,额外增加了不少的开支。
最好的实现应该如下
封装一个注入的扩展方法
/// <summary>
/// 添加Scope服务
/// </summary>
/// <typeparam name="TInterface"></typeparam>
/// <param name="services"></param>
/// <param name="types"></param>
/// <returns></returns>
public static IServiceCollection AddScoped<TInterface>(this IServiceCollection services, params Type[] types) where TInterface : class
{
foreach(var type in types)
{
services.AddScoped(type);
}
services.AddScoped(factory =>
{
Func<string, TInterface> accessor = key =>
{
var type = types.Where(a => a.GetAttribute<DescriptionAttribute>()?.Description == key || a.Name == key).FirstOrDefault();
return type == null ? null : (TInterface)factory.GetService(type);
};
return accessor;
});
return services;
}封装一个获取指定服务的方法
/// <summary>
/// 根据实现类描述获取服务
/// </summary>
/// <typeparam name="TService">服务</typeparam>
/// <param name="serviceProvider">服务驱动</param>
/// <param name="type">服务类型</param>
/// <returns></returns>
public static TService GetService<TService>(this IServiceProvider serviceProvider, Type type)
{
var services = serviceProvider.GetService<Func<string, TService>>();
return services(type.Name);
}调用方法如下
注入
services.AddScoped<ITestScopeContract>(typeof(TestScopeService), typeof(Test2ScopeService), typeof(Test3ScopeService));获取
//通过类型获取
var testScopeService = provider.GetService<ITestScopeContract>(typeof(TestScopeService));
testScopeService.CreateGuid();
//通过类描述获取
var testScopeService = provider.GetService<ITestScopeContract>("Test1");
testScopeService.CreateGuid();