通过注解 (特性) 的方式进行对象的注册与注入, 方便, 灵活!
本篇主要讲如何去实现, 下一篇主要讲如何把它集成到 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!
人类跑起来!
飞行第一步!
来源: https://www.cnblogs.com/lori/p/10696640.html