基于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

posted @ 2020-04-01 14:11  沉迷代码的萌新  阅读(966)  评论(1编辑  收藏  举报