VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > .net教程 >
  • ASP.net教程之设计一下类似SpringIoC的注入工具~Li

 

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

  • 本篇主要讲如何去实现,下一篇主要讲如何把它集成到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!
人类跑起来!
飞行第一步!

 


相关教程