类别
标签
C#扩展方法注册多个接口实现

在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();