当前位置: 移动技术网 > IT编程>开发语言>.net > 设计一下类似SpringIoC的注入工具~Lind.DI

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

2019年04月13日  | 移动技术网IT编程  | 我要评论

耒阳社区纸都在线,荒途传,865餐饮通

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

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网