zoukankan      html  css  js  c++  java
  • 设计一下类似SpringIoC的注入工具~Lind.DI

    通过注解(特性)的方式进行对象的注册与注入,方便,灵活!

    • 本篇主要讲如何去实现,下一篇主要讲如何把它集成到mvc和api环境里,实现自动的注入!

    spring ioc工作的过程大致为,统一的注册组件,拦截当前请求,统一的注入当前请求所需要的组件,事实上,说到这事,.net也完全可以实现这个功能和工作方式,下来大叔来实现一下

    1. 定义组件注册特性
    2. 定义组件生命周期
    3. 定义组件注入特性
    4. 定义Ioc工厂
    5. 使用灵活方便
    6. 将注入功能集成到mvc的拦截器里

    定义组件注册特性

    定义在类身上

        /// <summary>
        /// 注册组件特性.
        /// </summary>
        [AttributeUsage(AttributeTargets.Class)]
        public class ComponentAttribute : Attribute
        {
            public LifeCycle LifeCycle { get; set; } = LifeCycle.CurrentScope;
    
            public String Named { get; set; }
        }
    

    定义组件生命周期

        /// <summary>
        /// 组件生命周期
        /// </summary>
        public enum LifeCycle
        {
            CurrentScope,
            CurrentRequest,
            Global,
        }
    

    定义组件注入特性

    定义在字段上

        /// <summary>
        /// 注入一对象.
        /// </summary>
        [AttributeUsage(AttributeTargets.Field)]
        public class InjectionAttribute : Attribute
        {
            public string Named{get;set;}
        }
    

    定义Ioc工厂

        /// <summary>
        /// DI工厂.
        /// </summary>
        public class DIFactory
    	{
    
    		static IContainer container;
    
    		/// <summary>
    		/// 手动注入.
    		/// </summary>
    		/// <returns>The resolve.</returns>
    		/// <typeparam name="T">The 1st type parameter.</typeparam>
    		public static T Resolve<T>()
    		{
    			if (container == null)
    				throw new ArgumentException("please run DIFactory.Init().");
    			return container.Resolve<T>();
    		}
    
    		/// <summary>
    		/// 手动注入.
    		/// </summary>
    		/// <returns>The by named.</returns>
    		/// <param name="named">Named.</param>
    		/// <typeparam name="T">The 1st type parameter.</typeparam>
    		public static T ResolveByNamed<T>(string named)
    		{
    			if (container == null)
    				throw new ArgumentException("please run DIFactory.Init().");
    			return container.ResolveNamed<T>(named);
    		}
    
    
    	/// <summary>
            /// 把对象里的Inject特性的对象注入.
            /// web环境下,应该使用filter拦截器将当前控制器传传InjectFromObject去注入它.
            /// </summary>
            /// <param name="obj">Object.</param>
            public static void InjectFromObject(object obj)
            {
                if (obj.GetType().IsClass && obj.GetType() != typeof(string))
                    foreach (var field in obj.GetType().GetFields(
                        BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public))
                    {
                        if (field.GetCustomAttributes(false).Select(i => i.GetType())
                        .Contains(typeof(InjectionAttribute)))
                        {
                            InjectionAttribute inject = (InjectionAttribute)field.GetCustomAttributes(false).FirstOrDefault(i => i.GetType() == typeof(InjectionAttribute));
                            if (inject != null && !String.IsNullOrWhiteSpace(inject.Named))
                            {
                                field.SetValue(obj, container.ResolveNamed(inject.Named, field.FieldType));
                            }
                            else
                            {
                                field.SetValue(obj, container.Resolve(field.FieldType));
                            }
                            //递归处理它的内部字段
                            InjectFromObject(field.GetValue(obj));
                        }
    
                    }
            }
    
    		/// <summary>
    		/// 初始化.
    		/// </summary>
    		public static void Init()
    		{
    			var builder = new ContainerBuilder();
    			var arr = AppDomain.CurrentDomain.GetAssemblies().Where(
    				 x => !x.FullName.StartsWith("Dapper")
    				 && !x.FullName.StartsWith("System")
    				 && !x.FullName.StartsWith("AspNet")
    				 && !x.FullName.StartsWith("Microsoft"))
    				 .SelectMany(x => x.DefinedTypes)
    				 .Where(i => i.IsPublic && i.IsClass)
    				 .ToList();
    			foreach (var type in arr)
    			{
    				try
    				{
    					if (type.GetCustomAttributes(false).Select(i => i.GetType()).Contains(typeof(ComponentAttribute)))
    					{
    						ComponentAttribute componentAttribute = (ComponentAttribute)type.GetCustomAttributes(false).FirstOrDefault(o => o.GetType() == typeof(ComponentAttribute));
    
    						if (type.GetInterfaces() != null && type.GetInterfaces().Any())
    						{
    							type.GetInterfaces().ToList().ForEach(o =>
    							{
    								registor(builder, type, o, componentAttribute);
    
    							});
    						}
    						else
    						{
    							registor(builder, type, type, componentAttribute);
    						}
    					}
    				}
    				catch (Exception)
    				{
    					throw new Exception($"Lind.DI init {type.Name} error.");
    				}
    			}
    			container = builder.Build();
    		}
    
    		/// <summary>
    		/// 注册组件.
    		/// </summary>
    		/// <param name="builder">Builder.</param>
    		/// <param name="typeImpl">Type impl.</param>
    		/// <param name="type">Type.</param>
    		/// <param name="componentAttribute">Component attribute.</param>
    		static void registor(ContainerBuilder builder, Type typeImpl, Type type, ComponentAttribute componentAttribute)
    		{
    			if (componentAttribute.LifeCycle == LifeCycle.Global)
    			{
    				if (componentAttribute.Named != null)
    					builder.RegisterType(typeImpl).Named(componentAttribute.Named, type).SingleInstance();
    				else
    					builder.RegisterType(typeImpl).As(type).SingleInstance();
    			}
    			else if (componentAttribute.LifeCycle == LifeCycle.CurrentScope)
    			{
    				if (componentAttribute.Named != null)
    					builder.RegisterType(typeImpl).Named(componentAttribute.Named, type).InstancePerLifetimeScope();
    				else
    					builder.RegisterType(typeImpl).As(type).InstancePerLifetimeScope();
    			}
    			else
    			{
    				if (componentAttribute.Named != null)
    					builder.RegisterType(typeImpl).Named(componentAttribute.Named, type).InstancePerRequest();
    				else
    					builder.RegisterType(typeImpl).As(type).InstancePerRequest();
    			}
    		}
    	}
    

    使用灵活方便

    支持对象与对象之间的依赖

       [Component(Named="RunPeople")]
        public class RunPeople : IRun
        {
            public void Do()
            {
                System.Console.WriteLine("人类跑起来!");
            }
        }
        [Component]
        public class Fly
        {
            [Injection(Named="RunPeople")]
            Run run;
            public void step1()
            {
                run.Do();
                System.Console.WriteLine("飞行第一步!");
            }
        }
    

    使用方式,程序入口先初始化DIFactory.Init();

           [Injection]
            Fly flyObj;
            void print(){
                DIFactory.Init();
                DIFactory.InjectFromObject(this);
                flyObj.step1();
            }
            static void Main(string[] args)
            {
                DIFactory.Init();
                System.Console.WriteLine("Hello World!");
                new Program().print();
            }
    

    结果

    Hello World!
    人类跑起来!
    飞行第一步!
    
  • 相关阅读:
    Android Init语言
    Android Framework------之Input子系统
    Android Framework------之Keyguard 简单分析
    Android Framework------之ActivityManagerService与Activity之间的通信
    Android Framework------之PowerManagerService的功能
    蓝牙广播数据格式和动态改变
    蓝牙DA14580开发:固件格式、二次引导和烧写
    嵌入式调试器原理和各类调试器集锦(JLINK、STLINK、CCDEBUG)
    微信智能跑鞋技术解密
    国内物联网平台的发展、技术架构演进暨物联网解决方案发布
  • 原文地址:https://www.cnblogs.com/lori/p/10696640.html
Copyright © 2011-2022 走看看