• 基于AspectCore打造属性注入



    前言

    源自于晓晨在成都.net社区群的一篇文章 《晓晨的ASP.NET Core 奇淫技巧之伪属性注入》

    他的思路是 Ioc容器替换 ControllerActivator,因为只能在控制器内完成属性注入,意识心痒痒,就开笔写了这样一篇

    先分析一下属性注入的思路

    属性注入的核心就是通过动态代理完成注入,在这个过程中,对源实例的属性/字段注入实体

    想了一下,最近几天沉迷学习,没有写点什么技术分享了,又想起之前学习AspectCore的过程,就打算基于AspectCore制作属性注入


    设计思路如下

    可以看见无论是默认的特性注入AOP流程,还是我们自定义的代理工厂类,核心都是通过拦截执行过程到自定义的过滤器

    个人选择实现的方式是自定义工厂类,也可以根据代码,实现特性注入的方式注入属性

    到属性注入这一步,就是查找自定义的特性,有注入的特性的,则完成字段/属性注入


    实例实现

    属性注入的特性

        [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
        public class PropertyInjectAttribute: Attribute
        {
    
        }

    这个特性,我们约束了只能打在字段/属性上面

    自定义过滤器/过滤器工厂类

    过滤器

        internal class PropertyInjectInterceptor : IInterceptor
        {
            public bool AllowMultiple => true;
    
            public bool Inherited { get ; set; }
            public int Order { get; set; }
    
            public Task Invoke(AspectContext context, AspectDelegate next)
            {
                var instace = context.Implementation;
                var instanceType = instace.GetType();
    
                var serviceProvider = context.ServiceProvider;
    
                var bindingFlag = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
    
                foreach (var field in instanceType
                            .GetFields(bindingFlag)
                            .Where(_field =>
                                _field.GetCustomAttributes(typeof(PropertyInjectAttribute), true) != null &&
                                _field.GetCustomAttributes(typeof(PropertyInjectAttribute), true).Length > 0 &&
                                _field.FieldType.IsInterface
                            )
                )
                {
                    var value = field.GetReflector().GetValue(instace);
    
                    if (value == null)
                    {
                        var service = serviceProvider.GetRequiredService(field.FieldType);
    
                        field.GetReflector().SetValue(instace, service);
                    }
                }
    
                foreach (var property in instanceType
                            .GetProperties(bindingFlag)
                            .Where(_property =>
                                _property.GetCustomAttributes(typeof(PropertyInjectAttribute), true) != null &&
                                _property.GetCustomAttributes(typeof(PropertyInjectAttribute), true).Length > 0 &&
                                _property.PropertyType.IsInterface
                            )
                )
                {
                    var value = property.GetReflector().GetValue(instace);
    
                    if (value == null)
                    {
                        var service = serviceProvider.GetRequiredService(property.PropertyType);
    
                        property.GetReflector().SetValue(instace, service);
                    }
                }
    
                return next(context);
            }
        }

    过滤器工厂类

        public class PropertyInjectInterceptorFactory : InterceptorFactory
        {
            public override IInterceptor CreateInstance(IServiceProvider serviceProvider)
            {
                return serviceProvider.GetRequiredService<PropertyInjectInterceptor>();
            }
        }

    启用过滤器工厂类

                services.AddScoped<PropertyInjectInterceptor>();
                services.ConfigureDynamicProxy(config =>
                {
                    config.Interceptors.Add(new PropertyInjectInterceptorFactory());
                });
    
                return services.BuildDynamicProxyProvider();

    编写测试例子

        public interface IInterface
        {
            void Hello();
        }
    
        internal class InterfaceService : IInterface
        {
            [PropertyInject]
            private IPropertyServer propertyServer;
    
            [PropertyInject]
            private IPropertyServer _propertyServer { get; set; }
    
            public void Hello()
            {
                Console.WriteLine("Hello");
            }
        }
    
        [NonAspect]
        public interface IPropertyServer
        {
    
        }
    
        internal class PropertyServer: IPropertyServer
        {
    
        }

    属性注入的实现,我不想再被AOP代理一次,就打上了NopAspect特性,如果不介意的话,也可以不打


    后话

    我隐隐约约记得AspectCore是自带了属性注入的,奈何最近几天没写C#代码了,有点想念,就自己撸上,重复造轮子了

    分享嘛,思路最重要,使用而言,有成熟的轮子肯定不要自己造,学习的话,就要有勇于造轮子的心思

    打个小广告

    如果有技术交流可以加NCC的群 24791014、436035237,我在群里,有任何关于asp.net core方面的问题或者建议都可以与我交流,非常欢迎

    附上晓晨的链接

    《ASP.NET Core 奇淫技巧之伪属性注入》

    https://www.cnblogs.com/stulzq/p/12610026.html

  • 相关阅读:
    4、自定义菜单
    3、关注、取消关注 与 关键字回复
    2、自动回复消息
    1、接入公众平台
    java学习备忘录
    vue组件最佳实践
    js拉起或下载app
    angular1.5 Components
    Charlse 使用小记
    2016年终总结
  • 原文地址:https://www.cnblogs.com/NCoreCoder/p/12612242.html
Copyright © 2020-2023  润新知