设计一下类似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!
人类跑起来!
飞行第一步!
原文地址:https://www.cnblogs.com/lori/p/10696640.html