设计一下类似SpringIoC的注入工具~Lind.DI
程序员文章站
2022-06-10 08:58:59
通过注解(特性)的方式进行对象的注册与注入,方便,灵活! 本篇主要讲如何去实现,下一篇主要讲如何把它集成到mvc和api环境里,实现自动的注入! spring ioc工作的过程大致为,统一的注册组件,拦截当前请求,统一的注入当前请求所需要的组件,事实上,说到这事,.net也完全可以实现这个功能和工作 ......
通过注解(特性)的方式进行对象的注册与注入,方便,灵活!
-
本篇主要讲如何去实现,下一篇主要讲如何把它集成到mvc和api环境里,实现自动的注入!
spring ioc工作的过程大致为,统一的注册组件,拦截当前请求,统一的注入当前请求所需要的组件,事实上,说到这事,.net也完全可以实现这个功能和工作方式,下来大叔来实现一下
- 定义组件注册特性
- 定义组件生命周期
- 定义组件注入特性
- 定义ioc工厂
- 使用灵活方便
- 将注入功能集成到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! 人类跑起来! 飞行第一步!