di容器,DI 容器-Mini容器工作机制剖析(下篇)

上篇介绍了DI容器最基本功能,组件注册和组件创建和组件获取。这里将陆续把依赖注入进行详细介绍。
1. 看看组件工厂接口-IActivator的代码:
/// /// 组件工厂 /// public interface IActivator { /// /// 创建组件 /// /// 创建上下文
/// 返回所创建的组件 object Create(IPreCreationContext ctx); }
2. AbstractActivator 抽象组件工厂定义了创建组件的一系列模板步骤,具体的子类只要实现各自的具体步骤即可,下面是抽象组件工厂的源代码:
/// /// 抽象组件工厂 /// [Serializable] public abstract class AbstractActivator : BooleanDisposable, IActivator { private readonly object SyncRoot = new object(); private bool hasLock; /// /// 创建组件 /// /// 创建上下文
/// 返回所创建的组件 public virtual object Create(IPreCreationContext context) { //1. 记录并跟踪组件创建的对象图 Tracker.Track(context); //2. 检查是否循环依赖创建组件,如果是Throw LoopDependencyException if (hasLock) throw ExceptionManager.HandleAndWrapper(Tracker.CallStack); object instance = null; lock (SyncRoot) { hasLock = true; //3. 得到组件监听管理器 var componentListner = context.Kernel.ListenerManager as IComponentListener; //4. 在组件创建前进行监听 if (componentListner != null) componentListner.OnPreCreation(context); //5. 具体的 Create instance instance = InternalCreate(context); if (componentListner != null) { //6. 在组件创建后进行监听(这里就是依赖注入的扩张点) var postCreateContext = new PostCreationContext(context.Kernel, context.Component, instance); componentListner.OnPostCreation(postCreateContext); //7. 在组件创建后对组件初始化进行监听 componentListner.OnInitialization(postCreateContext); //8. 在组件初始化后进行监听 componentListner.OnPostInitialization(postCreateContext); } Tracker.Clear(); hasLock = false; } return instance; } /// /// /// ///
/// protected virtual object InternalCreate(IPreCreationContext context) { throw new NotImplementedException(); } }
通过代码可以看出组件工厂里面并没有提供任何依赖注入的扩展,但是有一系列组件监听器的监听方法:
  • OnPreCreation
  • OnPostCreation
  • OnInitialization
  • OnPostInitialization
通过这些监听方法可以非常方便的对组件内部的字段,属性进行初始化(也就是依赖注入)
3. 完整的组件监听器接口定义:
/// /// 组件监听阶段枚举 /// [Flags] public enum ComponentListenStage { /// /// 空 /// None = 1, /// /// 组件元数据注册后阶段 /// MetadataRegistered = None * 2, /// /// 组件创建前阶段 /// PreCreation = MetadataRegistered * 2, /// /// 组件创建后阶段 /// PostCreation = PreCreation * 2, /// /// 初始化阶段 /// Initialization = PostCreation * 2, /// /// 初始化后阶段 /// PostInitialization = Initialization * 2, /// /// 组件释放前阶段 /// PreDestroy = PostInitialization * 2, /// /// 组件释放后阶段 /// PostDestroy = PreDestroy * 2, } /// /// 组件监听器接口,在组件元数据注册,组件创建前后,组件初始化前后以及组件释放前后进行监听 /// [Contract] public interface IComponentListener:IListener { /// /// 初始化监听器 /// ///
void Init(IKernel kernel); /// /// 得到内核容器对象 /// IKernel Kernel { get; } /// /// 在组件元数据注册后进行监听,例如Aop监听器 /// ///
void _disibledevent=>
void _disibledevent=>
void _disibledevent=>
void _disibledevent=>
void _disibledevent=>
///
void _disibledevent=>
void _disibledevent=> 1 public Kernel( 2 IComponentListenerManager listnerManager, 3 ILifestyleManagerFactory lifestyleManagerRegistry, 4 IActivatorFactory activatorFactory, 5 IClassLoader classLoader) 6 { 7 ListenerManager = listnerManager; 8 LifestyleManagerRegistry = lifestyleManagerRegistry; 9 ActivatorRegistry = activatorFactory; 10 11 IdStores = new ConcurrentMap(StringComparer.OrdinalIgnoreCase); 12 TypeStores = new ConcurrentMap>(); 13 14 Listner = ListenerManager as IComponentListener; 15 16 RegisterInstance("ServiceLocator", typeof(IServiceLocator), this); 17 RegisterInstance("ServiceRegistry", typeof(IServiceRegistry), this); 18 19 20 if (classLoader != null) 21 RegisterInstance(AppDomain.CurrentDomain.Id.ToString() + ":" + classLoader.GetType(), typeof(IClassLoader), classLoader); 22 23 if (ListenerManager != null) 24 ListenerManager.Init(this); 25 26 RegisterListners(); 27 } 28 29 //注册默认监听器 30 private void RegisterListners() 31 { 32 ListenerManager.Register(new AopListener());//Aop监听器 33 ListenerManager.Register(new DisposalListener());//Dispose监听器 34 ListenerManager.Register(new InitializationListener());//初始化监听器 35 ListenerManager.Register(new SupportInitializeListener());//Support初始化监听器 36 ListenerManager.Register(new StartableListener());//启动停止监听器 37 ListenerManager.Register(new SubscribeListener());//消息总线的订阅监听器 38 ListenerManager.Register(new InjectionListener());//注入监听器 39 ListenerManager.Register(new InjectionManyListener());//批量注入监听器 40 ListenerManager.Register(new ComponentMemberRegisterListner());//组件成员导出与注入监听器 41 ListenerManager.Register(new AppSettingInjectionListener());//AppSetting注入监听器 42 }
5. Mini容器提供了很多监听器,下面看看注入监听器的代码:
using System.Linq; using NLite.Mini.Context; using NLite.Reflection; using NLite.Collections; using System.Reflection; using NLite.Mini.Internal; using NLite.Mini.Listener.Internal; using NLite.Reflection.Internal; namespace NLite.Mini.Listener { /// /// 注入监听器 /// public sealed class InjectionListener:ComponentListenerAdapter { private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const BindingFlags FieldFlags = BindingFlags.SetField | Flags; private const BindingFlags PropertyFlags = BindingFlags.SetProperty | Flags; /// /// /// public InjectionListener():base(ComponentListenStage.PostCreation) { } /// /// /// ///
public override void _disibledevent=> lazy = null; if (ctx.Component.ExtendedProperties.Contains(Key)) lazy = ctx.Component.ExtendedProperties[Key] as Lazy; if (lazy == null)//基于Lazy的方式创建组件的注入元数据 { lazy = new Lazy(() => { var instanceType = ctx.Instance.GetType(); return (from f in instanceType.GetFields(FieldFlags) let att = f.GetAttribute(true)//字段上有InjectAttribute标签 let ignoreAtt = f.GetAttribute(true) let id = att != null ? att.Id : string.Empty where ignoreAtt == null where att != null where !f.HasAttribute(false) select new InjectionInfo//字段注入元数据 { Id = id , Source = InjectionSource.Container , Setter = f.ToMemberSetter()//通过Emit的方式进行注入 , MemberType = f.FieldType } ) .Union( from p in instanceType.GetProperties(PropertyFlags) let ps = p.GetIndexParameters() let att = p.GetAttribute(false) let ignoreAtt = p.GetAttribute(false) let id = att != null ? att.Id : string.Empty where ignoreAtt == null || ps == null || ps.Length == 0 where att != null where !p.HasAttribute(false) select new InjectionInfo//属性注入元数据 { Id = id , Setter = p.ToMemberSetter()//通过Emit的方式进行注入 , MemberType = p.PropertyType , Source = InjectionSource.Container }) .Union( from m in instanceType.GetMethods(Flags) let ps = m.GetParameters() let att = m.GetAttribute(false) let ignoreAtt = m.GetAttribute(false) where ignoreAtt == null && m.ReturnType == Types.Void && att != null && ps.TrueForAll(p => !p.HasAttribute(false)) select new InjectionInfo//方法注入元数据 { Id = att.Id , Method = DynamicMethodFactory.GetProc(m) , Parameters = ps , Source = InjectionSource.Container } ).ToArray(); }); ctx.Component.ExtendedProperties[Key] = lazy; } if (lazy.Value.Length == 0)//没有注入元数据则返回 return; foreach (var item in lazy.Value) { if (item.MemberType != null)//是字段或属性注入吗 InjectMember(ctx, item); else InjectMemberByMethod(ctx, item);//方法注入 } } //执行方法注入 private static void InjectMemberByMethod(IPostCreationContext ctx, IInjectionInfo item) { item.Method(ctx.Instance, ReflectionHelper.GetParameters(ctx.Kernel, item.Parameters)); } //执行字段注或属性注入 private static void InjectMember(IPostCreationContext ctx, IInjectionInfo item) { if (!MemberMatcher.Match(item.MemberType, ctx.Kernel)) return; item.Setter(ctx.Instance, InjectService.Get(item.Id, item.MemberType, ctx.Kernel, false)); } } }
从注入监听器的代码中可以看出,当组件创建后,注入监听器将扫描组件的所有字段,属性和方法,找出所有可以被注入的成员,然后对这些成员进行注入。
具体注入的过程就是,通过注入的元数据找到依赖的组件类型或组件Id,然后根据组件类型或Id从DI容器中找出对应的依赖组件,然后把该依赖的组件通过字段,属性或方法调用的方式进行初始化,这样就完成了注入。
上篇文章全是文字没有代码,这篇基本上全是用代码堆起来的,文字很少,不过代码中有很多注释,通过代码注释基本上可以了解整个被注入的过程。通过这两篇文章已经把Mini容器的整个精髓和骨架勾勒出来,注册组件->创建组件元数据(Id,组件类型,组件契约,生命周期管理器,组件工厂),获取组件->组件生命周期管理器->组件工厂->组件监听器(依赖注入等),通过上篇的脑图可以更详细的了解Mini容器的内部结构, 望能够给那些对DI容器不太了解或对DI容器工作机制不太了解的朋友给些帮助,这样就够了!
为了加深大家对Mini容器DI容器更进一步了解,下面提供3个有关字段注入,属性注入,方法注入等的链接

Mini 容器学习笔记7——构造函数注入

Mini 容器学习笔记8——字段注入

Mini 容器学习笔记9——属性注入

Mini 容器学习笔记10——方法注入

Mini 容器学习笔记11——Lazy注入

Tags:  压力容器 奔奔mini 宝马mini n97mini di容器

延伸阅读

最新评论

发表评论