net core天馬行空系列: 一個接口多個實現類,利用mixin技術經過自定義服務名,實現精準屬性注入

系列目錄

1.net core天馬行空系列:原生DI+AOP實現spring boot註解式編程css

2.net core天馬行空系列: 泛型倉儲和聲明式事物實現最優雅的crud操做html

       哈哈哈哈,你們好,我就是高產似母豬的三合。平常開發中,咱們常會遇到這樣的場景,一個接口,有多個實現類,在某個業務中,咱們但願指定某個實現類,現在網絡上常見的解決方案,就是注入一個委託或者利用工廠模式,這些方式雖然能實現功能,但使用起來仍是不夠優雅,如何才稱得上優雅呢?天然是在添加服務的時候給服務指定名稱,注入的時候根據名稱來進行注入,沒錯,就是相似spring boot裏的@Qualifier註解,那麼net core能實現這個註解麼?要知道net core裏的原生DI並不支持在註冊的時候給服務添加名稱,因此實現起來也是難上加難,可是,利用動態代理,咱們就能完美解決這個問題,沒錯,他Lei了,net core版[QualifierAttribute],實現這個註解用到的最核心的技術,就是動態代理中很是重要的mixin,什麼是mixin呢?玩過less的小夥伴可能會知道,這玩意能夠把2個css樣式混合成一個,而在net core中,DP(castle.dynamicproxy)提供的mixin技術,能夠在程序運行時,把多個類混合成一個動態代理類,這個混合類既能夠用做類1,又能夠用做類2,那麼思路就很清晰了,類1就是咱們注入的服務類,類2須要咱們自定義,在咱們的這個自定義類中,咱們能夠添加一個Name的屬性,這樣在註冊服務的時候給服務命名,到了注入的時候,咱們就能夠根據名稱來進行精準地的屬性注入。BTW,動態代理,註解式編程,AOP貫穿本系列始終,no bb,正文開始。spring

1.定義用到的類

定義QualifierAttribute註解編程

 public class QualifierAttribute : Attribute
    {
        public string Name { get; }

        public QualifierAttribute(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException("服務名稱不能爲空");
            }

            this.Name = name;
        }
    }

定義用來進行混合的附加類接口IDependencyAddition和他的實現類DependencyAddition,類裏面只有一個名稱的屬性。cookie

public interface IDependencyAddition
    {
        string Name { set; get; }
    }
 public class DependencyAddition : IDependencyAddition
    {
        public string Name { set; get; }
    }

第一篇文章裏,講過有一輛汽車,汽車裏有引擎,咱們在這基礎上進行擴展,汽車老是有輪胎的,咱們定義一個輪胎接口IWheel和他的2個實現類WheelA和WheelB,類裏只有一個Scroll方法,表示輪胎在滾,同時向控制檯輸出他們是哪一種輪胎。網絡

 public interface IWheel
    {
        void Scroll();
    }
  public class WheelA : IWheel
    {
        public void Scroll()
        {
            Console.WriteLine("我是A輪胎,我正在滾");
        }
    }
 public class WheelB : IWheel
    {
        public void Scroll()
        {
            Console.WriteLine("我是B輪胎,我正在滾");
        }
    }

修改汽車類接口ICar和他的實現類Car,主要就是添加了輪胎的屬性注入,而且用[Qualifier("B輪胎")]註解指定使用哪一種輪胎,而後調用Scroll方法,讓輪胎滾起來。less

   public interface ICar
    {
        Engine Engine { set; get; }

        IWheel Wheel { set; get; }

        void Fire();
    }
   public class Car : ICar
    {
        [Autowired]
        public Engine Engine { set; get; }

        [Value("oilNo")]
        public int OilNo { set; get; }

        [Autowired]
        [Qualifier("B輪胎")]
        public IWheel Wheel { set; get; }

        [Transactional]
        public void Fire()
        {
            Console.WriteLine("加滿" + OilNo + "號汽油,點火");

            Wheel.Scroll();

            Engine.Start();
        }
    }

IServiceCollection的靜態擴展類SummerBootExtentions,和上一篇相比,主要是添加了AddSbService的新重載,使註冊服務的時候可以爲服務添加名稱,在這基礎上進一步封裝了AddSbSingleton,AddSbScoped和AddSbTransient方法。還有在工廠委託函數裏進行屬性注入的時候,添加了支持[QualifierAttribute]註解的邏輯,完整類代碼以下:ide

public static class SummerBootExtentions
    {
        /// <summary>
        /// 瞬時
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <typeparam name="TImplementation"></typeparam>
        /// <param name="services"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbTransient<TService, TImplementation>(this IServiceCollection services, params Type[] interceptorTypes)
        {
            return services.AddSbService(typeof(TService), typeof(TImplementation), ServiceLifetime.Transient, interceptorTypes);
        }

        /// <summary>
        /// 瞬時
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceType"></param>
        /// <param name="implementationType"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbTransient(this IServiceCollection services, Type serviceType,
            Type implementationType, params Type[] interceptorTypes)
        {
            return services.AddSbService(serviceType, implementationType, ServiceLifetime.Transient, interceptorTypes);
        }

        /// <summary>
        /// 請求級別
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <typeparam name="TImplementation"></typeparam>
        /// <param name="services"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbScoped<TService, TImplementation>(this IServiceCollection services, params Type[] interceptorTypes)
        {
            return services.AddSbService(typeof(TService), typeof(TImplementation), ServiceLifetime.Scoped, interceptorTypes);
        }

        /// <summary>
        /// 請求級別
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceType"></param>
        /// <param name="implementationType"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbScoped(this IServiceCollection services, Type serviceType,
            Type implementationType, params Type[] interceptorTypes)
        {
            return services.AddSbService(serviceType, implementationType, ServiceLifetime.Scoped, interceptorTypes);
        }

        /// <summary>
        /// 單例
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <typeparam name="TImplementation"></typeparam>
        /// <param name="services"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbSingleton<TService, TImplementation>(this IServiceCollection services, params Type[] interceptorTypes)
        {
            return services.AddSbService(typeof(TService), typeof(TImplementation), ServiceLifetime.Singleton, interceptorTypes);
        }

        /// <summary>
        /// 單例
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceType"></param>
        /// <param name="implementationType"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbSingleton(this IServiceCollection services, Type serviceType,
            Type implementationType, params Type[] interceptorTypes)
        {
            return services.AddSbService(serviceType, implementationType, ServiceLifetime.Singleton, interceptorTypes);
        }

        public static IServiceCollection AddSbService(this IServiceCollection services, Type serviceType, Type implementationType,
            ServiceLifetime lifetime, params Type[] interceptorTypes)
        {
            services.Add(new ServiceDescriptor(implementationType, implementationType, lifetime));

            object Factory(IServiceProvider provider)
            {
                var target = provider.GetService(implementationType);
                var properties = implementationType.GetTypeInfo().DeclaredProperties;

                foreach (PropertyInfo info in properties)
                {
                    //屬性注入
                    if (info.GetCustomAttribute<AutowiredAttribute>() != null)
                    {
                        var propertyType = info.PropertyType;
                        object impl = null;
                        var qualifierAttribute = info.GetCustomAttribute<QualifierAttribute>();
                        if (qualifierAttribute != null)
                        {
                            var serviceName = qualifierAttribute.Name;
                            var implList = provider.GetServices(propertyType);
                            foreach (var tmpImpl in implList)
                            {
                                if (ProxyUtil.IsProxy(tmpImpl))
                                {
                                    var addition = tmpImpl as IDependencyAddition;
                                    if (addition?.Name == serviceName)
                                    {
                                        impl = tmpImpl;
                                        break; ;
                                    }
                                }
                            }
                        }
                        else
                        {
                            impl = provider.GetService(propertyType);
                        }

                        if (impl != null)
                        {
                            info.SetValue(target, impl);
                        }
                    }

                    //配置值注入
                    if (info.GetCustomAttribute<ValueAttribute>() is ValueAttribute valueAttribute)
                    {
                        var value = valueAttribute.Value;
                        if (provider.GetService(typeof(IConfiguration)) is IConfiguration configService)
                        {
                            var pathValue = configService.GetSection(value).Value;
                            if (pathValue != null)
                            {
                                var pathV = Convert.ChangeType(pathValue, info.PropertyType);
                                info.SetValue(target, pathV);
                            }
                        }

                    }
                }

                List<IInterceptor> interceptors = interceptorTypes.ToList()
                    .ConvertAll<IInterceptor>(interceptorType => provider.GetService(interceptorType) as IInterceptor);

                var proxyGenerator = provider.GetService<ProxyGenerator>();
                var proxy = proxyGenerator.CreateInterfaceProxyWithTarget(serviceType, target, interceptors.ToArray());

                return proxy;
            };

            var serviceDescriptor = new ServiceDescriptor(serviceType, Factory, lifetime);
            services.Add(serviceDescriptor);

            return services;
        }

        /// <summary>
        /// 瞬時
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="services"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbTransient<TService>(this IServiceCollection services, params Type[] interceptorTypes)
        {
            return services.AddSbService(typeof(TService), ServiceLifetime.Transient, interceptorTypes);
        }

        /// <summary>
        /// 瞬時
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceType"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbTransient(this IServiceCollection services, Type serviceType, params Type[] interceptorTypes)
        {
            return services.AddSbService(serviceType, ServiceLifetime.Transient, interceptorTypes);
        }

        /// <summary>
        /// 請求
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="services"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbScoped<TService>(this IServiceCollection services, params Type[] interceptorTypes)
        {
            return services.AddSbService(typeof(TService), ServiceLifetime.Scoped, interceptorTypes);
        }

        /// <summary>
        /// 請求
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceType"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbScoped(this IServiceCollection services, Type serviceType,
             params Type[] interceptorTypes)
        {
            return services.AddSbService(serviceType, ServiceLifetime.Scoped, interceptorTypes);
        }

        /// <summary>
        /// 單例
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="services"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbSingleton<TService>(this IServiceCollection services, params Type[] interceptorTypes)
        {
            return services.AddSbService(typeof(TService), ServiceLifetime.Singleton, interceptorTypes);
        }

        /// <summary>
        /// 單例
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceType"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbSingleton(this IServiceCollection services, Type serviceType, params Type[] interceptorTypes)
        {
            return services.AddSbService(serviceType, ServiceLifetime.Singleton, interceptorTypes);
        }

        public static IServiceCollection AddSbService(this IServiceCollection services, Type serviceType,
            ServiceLifetime lifetime, params Type[] interceptorTypes)
        {
            if (services == null)
                throw new ArgumentNullException(nameof(services));
            if (serviceType == (Type)null)
                throw new ArgumentNullException(nameof(serviceType));

            object Factory(IServiceProvider provider)
            {
                List<IInterceptor> interceptors = interceptorTypes.ToList()
                    .ConvertAll<IInterceptor>(interceptorType => provider.GetService(interceptorType) as IInterceptor);

                var proxyGenerator = provider.GetService<ProxyGenerator>();

                var proxy = proxyGenerator.CreateClassProxy(serviceType, interceptors.ToArray());

                var properties = serviceType.GetTypeInfo().DeclaredProperties;

                foreach (PropertyInfo info in properties)
                {
                    //屬性注入
                    if (info.GetCustomAttribute<AutowiredAttribute>() != null)
                    {
                        var propertyType = info.PropertyType;
                        object impl = null;
                        var qualifierAttribute = info.GetCustomAttribute<QualifierAttribute>();
                        if (qualifierAttribute != null)
                        {
                            var serviceName = qualifierAttribute.Name;
                            var implList = provider.GetServices(propertyType);
                            foreach (var tmpImpl in implList)
                            {
                                if (ProxyUtil.IsProxy(tmpImpl))
                                {
                                    var addition = tmpImpl as IDependencyAddition;
                                    if (addition?.Name == serviceName)
                                    {
                                        impl = tmpImpl;
                                        break; ;
                                    }
                                }
                            }
                        }
                        else
                        {
                            impl = provider.GetService(propertyType);
                        }

                        if (impl != null)
                        {
                            info.SetValue(proxy, impl);
                        }
                    }
                    //配置值注入
                    if (info.GetCustomAttribute<ValueAttribute>() is ValueAttribute valueAttribute)
                    {
                        var value = valueAttribute.Value;
                        if (provider.GetService(typeof(IConfiguration)) is IConfiguration configService)
                        {
                            var pathValue = configService.GetSection(value).Value;
                            if (pathValue != null)
                            {
                                var pathV = Convert.ChangeType(pathValue, info.PropertyType);
                                info.SetValue(proxy, pathV);
                            }
                        }
                    }
                }

                return proxy;
            };

            var serviceDescriptor = new ServiceDescriptor(serviceType, Factory, lifetime);
            services.Add(serviceDescriptor);

            return services;
        }

        /// <summary>
        /// 添加summer boot擴展
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IMvcBuilder AddSB(this IMvcBuilder builder)
        {
            if (builder == null)
                throw new ArgumentNullException(nameof(builder));
            ControllerFeature feature = new ControllerFeature();
            builder.PartManager.PopulateFeature<ControllerFeature>(feature);
            foreach (Type type in feature.Controllers.Select<TypeInfo, Type>((Func<TypeInfo, Type>)(c => c.AsType())))
                builder.Services.TryAddTransient(type, type);
            builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, SbControllerActivator>());

            return builder;
        }

        public static IServiceCollection AddSbRepositoryService(this IServiceCollection services, params Type[] interceptorTypes)
        {
            var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(it => it.GetTypes());

            var tableType = types.Where(it => it.GetCustomAttribute<TableAttribute>() != null);

            foreach (var type in tableType)
            {
                var injectServiceType = typeof(IRepository<>).MakeGenericType(type);
                var injectImplType = typeof(BaseRepository<>).MakeGenericType(type);
                services.AddSbScoped(injectServiceType, injectImplType, interceptorTypes);
            }

            return services;
        }

        /// <summary>
        /// 瞬時
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <typeparam name="TImplementation"></typeparam>
        /// <param name="services"></param>
        /// <param name="name"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbTransient<TService, TImplementation>(this IServiceCollection services, string name = "", params Type[] interceptorTypes)
        {
            return services.AddSbService(typeof(TService), typeof(TImplementation), ServiceLifetime.Transient, name, interceptorTypes);
        }

        /// <summary>
        /// 瞬時
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceType"></param>
        /// <param name="implementationType"></param>
        /// <param name="name"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbTransient(this IServiceCollection services, Type serviceType,
            Type implementationType, string name = "", params Type[] interceptorTypes)
        {
            return services.AddSbService(serviceType, implementationType, ServiceLifetime.Transient, name, interceptorTypes);
        }

        /// <summary>
        /// 請求級別
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <typeparam name="TImplementation"></typeparam>
        /// <param name="services"></param>
        /// <param name="name"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbScoped<TService, TImplementation>(this IServiceCollection services, string name = "", params Type[] interceptorTypes)
        {
            return services.AddSbService(typeof(TService), typeof(TImplementation), ServiceLifetime.Scoped, name, interceptorTypes);
        }

        /// <summary>
        /// 請求級別
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceType"></param>
        /// <param name="implementationType"></param>
        /// <param name="name"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbScoped(this IServiceCollection services, Type serviceType,
            Type implementationType, string name = "", params Type[] interceptorTypes)
        {
            return services.AddSbService(serviceType, implementationType, ServiceLifetime.Scoped, name, interceptorTypes);
        }

        /// <summary>
        /// 單例
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <typeparam name="TImplementation"></typeparam>
        /// <param name="services"></param>
        /// <param name="name"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbSingleton<TService, TImplementation>(this IServiceCollection services, string name = "", params Type[] interceptorTypes)
        {
            return services.AddSbService(typeof(TService), typeof(TImplementation), ServiceLifetime.Singleton, name, interceptorTypes);
        }

        /// <summary>
        /// 單例
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceType"></param>
        /// <param name="implementationType"></param>
        /// <param name="name"></param>
        /// <param name="interceptorTypes"></param>
        /// <returns></returns>
        public static IServiceCollection AddSbSingleton(this IServiceCollection services, Type serviceType,
            Type implementationType, string name = "", params Type[] interceptorTypes)
        {
            return services.AddSbService(serviceType, implementationType, ServiceLifetime.Singleton, name, interceptorTypes);
        }

        public static IServiceCollection AddSbService(this IServiceCollection services, Type serviceType, Type implementationType,
            ServiceLifetime lifetime, string name = "", params Type[] interceptorTypes)
        {
            services.Add(new ServiceDescriptor(implementationType, implementationType, lifetime));

            object Factory(IServiceProvider provider)
            {
                var target = provider.GetService(implementationType);
                var properties = implementationType.GetTypeInfo().DeclaredProperties;

                foreach (PropertyInfo info in properties)
                {
                    //屬性注入
                    if (info.GetCustomAttribute<AutowiredAttribute>() != null)
                    {
                        var propertyType = info.PropertyType;
                        object impl = null;
                        var qualifierAttribute = info.GetCustomAttribute<QualifierAttribute>();
                        if (qualifierAttribute != null)
                        {
                            var serviceName = qualifierAttribute.Name;
                            var implList = provider.GetServices(propertyType);
                            foreach (var tmpImpl in implList)
                            {
                                if (ProxyUtil.IsProxy(tmpImpl))
                                {
                                    var addition = tmpImpl as IDependencyAddition;
                                    if (addition?.Name == serviceName)
                                    {
                                        impl = tmpImpl;
                                        break; ;
                                    }
                                }
                            }
                        }
                        else
                        {
                            impl = provider.GetService(propertyType);
                        }

                        if (impl != null)
                        {
                            info.SetValue(target, impl);
                        }
                    }

                    //配置值注入
                    if (info.GetCustomAttribute<ValueAttribute>() is ValueAttribute valueAttribute)
                    {
                        var value = valueAttribute.Value;
                        if (provider.GetService(typeof(IConfiguration)) is IConfiguration configService)
                        {
                            var pathValue = configService.GetSection(value).Value;
                            if (pathValue != null)
                            {
                                var pathV = Convert.ChangeType(pathValue, info.PropertyType);
                                info.SetValue(target, pathV);
                            }
                        }

                    }
                }

                List<IInterceptor> interceptors = interceptorTypes.ToList()
                    .ConvertAll<IInterceptor>(interceptorType => provider.GetService(interceptorType) as IInterceptor);

                var proxyGenerator = provider.GetService<ProxyGenerator>();
                var options = new ProxyGenerationOptions();
                options.AddMixinInstance(new DependencyAddition() { Name = name });
                var proxy = proxyGenerator.CreateInterfaceProxyWithTarget(serviceType, target, options, interceptors.ToArray());

                return proxy;
            };

            var serviceDescriptor = new ServiceDescriptor(serviceType, Factory, lifetime);
            services.Add(serviceDescriptor);

            return services;
        }
    }
View Code

修改第一篇中自定義的控制器激活類SbControllerActivator,添加支持[QualifierAttribute]註解的邏輯。函數

 public class SbControllerActivator : IControllerActivator
    {
        /// <inheritdoc />
        public object Create(ControllerContext actionContext)
        {
            if (actionContext == null)
                throw new ArgumentNullException(nameof(actionContext));

            Type serviceType = actionContext.ActionDescriptor.ControllerTypeInfo.AsType();

            var target = actionContext.HttpContext.RequestServices.GetRequiredService(serviceType);

            var properties = serviceType.GetTypeInfo().DeclaredProperties;

            var proxyGenerator = actionContext.HttpContext.RequestServices.GetService<ProxyGenerator>();

            var proxy = proxyGenerator.CreateClassProxyWithTarget(serviceType, target);

            foreach (PropertyInfo info in properties)
            {
                //屬性注入
                if (info.GetCustomAttribute<AutowiredAttribute>() != null)
                {
                    var propertyType = info.PropertyType;
                    object impl = null;
                    var qualifierAttribute = info.GetCustomAttribute<QualifierAttribute>();
                    if (qualifierAttribute != null)
                    {
                        var serviceName = qualifierAttribute.Name;
                        var implList = actionContext.HttpContext.RequestServices.GetServices(propertyType);
                        foreach (var tmpImpl in implList)
                        {
                            if (ProxyUtil.IsProxy(tmpImpl))
                            {
                                var addition = tmpImpl as IDependencyAddition;
                                if (addition?.Name == serviceName)
                                {
                                    impl = tmpImpl;
                                    break; ;
                                }
                            }
                        }
                    }
                    else
                    {
                        impl = actionContext.HttpContext.RequestServices.GetService(propertyType);
                    }

                    if (impl != null)
                    {
                        info.SetValue(proxy, impl);
                    }
                }

                //配置值注入
                if (info.GetCustomAttribute<ValueAttribute>() is ValueAttribute valueAttribute)
                {
                    var value = valueAttribute.Value;
                    if (actionContext.HttpContext.RequestServices.GetService(typeof(IConfiguration)) is IConfiguration configService)
                    {
                        var pathValue = configService.GetSection(value).Value;
                        if (pathValue != null)
                        {
                            var pathV = Convert.ChangeType(pathValue, info.PropertyType);
                            info.SetValue(proxy, pathV);
                        }
                    }

                }
            }

            return proxy;
        }

        /// <inheritdoc />
        public virtual void Release(ControllerContext context, object controller)
        {
        }
    }
View Code

修改Startup.cs類裏的ConfigureServices方法,能夠看到,咱們在註冊WheelA和WheelB的時候,爲服務添加了名稱,而且隨手添加了個攔截器,代碼以下:ui

 public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });


            services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
                .AddSB();

            services.AddSingleton<ProxyGenerator>();

            services.AddSbScoped<Engine>(typeof(TransactionalInterceptor));

            services.AddSbScoped<IUnitOfWork, UnitOfWork>();
            services.AddScoped(typeof(TransactionalInterceptor));

            services.AddSbScoped<ICar, Car>(typeof(TransactionalInterceptor));

            services.AddSbScoped<IDbFactory, DbFactory>();
            services.AddSbRepositoryService(typeof(TransactionalInterceptor));
            services.AddSbScoped<IAddOilService, AddOilService>(typeof(TransactionalInterceptor));

            services.AddSbScoped<IWheel, WheelA>("A輪胎", typeof(TransactionalInterceptor));
            services.AddSbScoped<IWheel, WheelB>("B輪胎", typeof(TransactionalInterceptor));
        }

 控制器類HomeController,代碼以下:

public class HomeController : Controller
    {
        [Autowired]
        public ICar Car { set; get; }

        [Autowired]
        public IDistributedCache Cache { set; get; }

        [Value("description")]
        public string Description { set; get; }

        [Autowired]
        public IAddOilService AddOilService { set; get; }

        public IActionResult Index()
        {

            var car = Car;

            AddOilService.AddOil();

            Car.Fire();

            Console.WriteLine(Description);

            return View();
        }
    }

核心原理,從SummerBootExtentions類完整源碼裏單獨抽取mixin服務註冊和屬性注入的代碼,能夠看到在生成動態代理的時候,在option裏添加了mixin實例,也就是咱們自定義的DependencyAddition,裏面包含了這個服務的名稱,在注入時,判斷是否有[QualifierAttribute]註解,若是有,就獲取整個接口的實現類列表,在循環裏,判斷是否爲動態代理類,若是是,就把每一個類實例強轉爲附加類接口IDependencyAddition,而後獲取名稱,若是名稱和咱們[QualifierAttribute]註解指定的名稱相同,則注入。

 var proxyGenerator = provider.GetService<ProxyGenerator>();
                var options = new ProxyGenerationOptions();
                options.AddMixinInstance(new DependencyAddition() { Name = name });
                var proxy = proxyGenerator.CreateInterfaceProxyWithTarget(serviceType, target, options, interceptors.ToArray());
//屬性注入
                    if (info.GetCustomAttribute<AutowiredAttribute>() != null)
                    {
                        var propertyType = info.PropertyType;
                        object impl = null;
                        var qualifierAttribute = info.GetCustomAttribute<QualifierAttribute>();
                        if (qualifierAttribute != null)
                        {
                            var serviceName = qualifierAttribute.Name;
                            var implList = provider.GetServices(propertyType);
                            foreach (var tmpImpl in implList)
                            {
                                if (ProxyUtil.IsProxy(tmpImpl))
                                {
                                    var addition = tmpImpl as IDependencyAddition;
                                    if (addition?.Name == serviceName)
                                    {
                                        impl = tmpImpl;
                                        break; ;
                                    }
                                }
                            }
                        }
                        else
                        {
                            impl = provider.GetService(propertyType);
                        }

                        if (impl != null)
                        {
                            info.SetValue(target, impl);
                        }
                    }

2.效果圖

先注入A輪胎

從上圖能夠看到,生成的動態代理類裏包含了Name這個屬性,而且名稱爲A輪胎。

控制檯輸出,也顯示了「我是A輪胎,我正在滾」,符合預期。

注入B輪胎

從上圖能夠看到,生成的動態代理類裏包含了Name這個屬性,而且名稱爲B輪胎。

控制檯輸出,也顯示了「我是B輪胎,我正在滾」,符合預期。

3. 寫在最後

        經過[Autowired]註解和[Qualifier("B輪胎")]註解聯合使用,咱們就實現了一個接口多個實現類的精準屬性注入,代碼看起來是否是舒服多了呢~,我始終相信,若是一件事我講的別人聽不明白,那必定是我講的不夠有趣,不夠通俗易懂,因此大白話是必須的,若是文章還有哪裏說得太深奧,歡迎給我指出來,同時net core裏還有啥功能讓你以爲用起來特別彆扭的,請!必定!告訴我!,i will try it,由於這特別有趣,由於我一直踐行的編程理念就是萬物靠注入,萬物可攔截,萬物皆註解,始終相信IOC和AOP是構建軟件的基石,哈哈哈哈哈。

        若是這篇文章對你有所幫助,不妨點個贊咯。

相關文章
相關標籤/搜索