欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

设计一下类似SpringIoC的注入工具~Lind.DI

程序员文章站 2022-03-04 13:16:57
通过注解(特性)的方式进行对象的注册与注入,方便,灵活! 本篇主要讲如何去实现,下一篇主要讲如何把它集成到mvc和api环境里,实现自动的注入! spring ioc工作的过程大致为,统一的注册组件,拦截当前请求,统一的注入当前请求所需要的组件,事实上,说到这事,.net也完全可以实现这个功能和工作 ......

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

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