本文旨在通过创建一棵插件树来演示条件绑定和元数据的用法. 说“插件树”也许不大妥当,因为在一般观念中,谈到插件树,我们很容易会想到 Winform/Wpf 中的菜单.举例来说,如果要在 Winform 中创建一个层级菜单,我们可以使用类似如下代码: // Create File menu var newMenu = new ToolStripMenuItem(); var localProjectMenu = new ToolStripMenuItem(); var remoteProjectM…
在 Ioc 世界中,有些框架(例如 Autofac/NInject/Unity)支持传递默认参数,有些框架(例如 SimpleInjector/LightInjector 等)则不支持.作为 My.Ioc 来说,我们支持默认参数. 当我们在 My.Ioc 中注册对象时,有些对象类型 (System.Type) 要求我们必须提供默认参数,而有些则不是必要的.在 My.Ioc 中,默认参数有两个作用:1. 容器根据默认参数来选择用于构建对象的构造函数.而一旦选定构造函数之后,今后容器便会一直使用该构…
在 My.Ioc 中,我们可以指定让容器在构建好对象实例之后,自动为我们调用对象的公共方法或是为对象的公共属性赋值.在解析对象实例时,容器将根据我们在注册对象时指定的方法调用或属性赋值的先后顺序,调用对象的实例方法或为其属性赋值. 用法比较简单,请看下面的示例代码: using System; using System.Diagnostics; using My.Ioc; namespace PropertyAndMethodInjection { #region Test Types publ…
在很多 Ioc 容器中,当使用者向容器请求实现了某个契约类型 (Contract Type) 的服务时 (调用类似如下方法 container.Resolve(Type contractType)),如果该服务尚未注册,而且该契约类型符合某种约定,那么容器将会自动为将该契约类型创建一个注册项 (Registration),并将该注册项添加到容器中,然后使用该注册项创建一个服务实例并将其返回给使用者. 例如,在 asp.net 应用程序中,假设我们有这样一个约定“只要契约类型是具体引用类型(不是值…
在 My.Ioc 中,要想在服务注销/注册时获得通知,可以通过订阅 ObjectBuilderRegistered 和 ObjectBuilderUnregistering 这两个事件来实现.但是,使用这两个事件也有一些不足.首先,它们只能针对当前注册/注销的服务发出通知,而对于依赖当前服务的上层服务的激活/停用事件(由于当前服务的注册/注销而引起的),它们则无能为力:其次,这两者都是针对所有注册项的广播事件.也就是说,只要发生注册/注销,无论注册/注销的是什么服务,容器都会向所有订阅了这两个事…
在使用 Ioc 框架时,一般我们建议集中在一个称为 Composition Root(其含义请参见下面的小注)的位置来注册 (Register) 和解析 (Resolve) 服务.这种做法的目的在于限制 Ioc 的使用场合,防止在应用程序中到处引用 Ioc 框架,从而尽量减少应用程序本身对于 Ioc 框架的依赖. 上述模式固然能够很好地解耦应用程序和 Ioc 框架,使我们能够在需要的时候方便地更换 Ioc 框架,但它同时也带来了一个问题:难道我们一定要在程序启动时注册所有服务吗?有些服务并不一定…
装饰器模式体现了一种“组合优于继承”的思想.当我们要动态为对象增加新功能时,装饰器模式往往是我们的好帮手. 很多后期出现的 Ioc 容器都为装饰器模式提供了支持,比如说 Autofac.在 My.Ioc 中,默认不提供装饰器支持,但我们可以自己进行扩展,以提供此项功能. using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using My.Ioc; u…
当您需要从 Ioc 容器中注销/删除一个注册项的时候,您会怎么做呢? 有人曾经在 stackoverflow 上提问“如何从 Unity 中注销一个注册项”.对于这个问题,有人的回答是“有趣.你为什么要这样做?”,也有人试图提出一些变通的解决办法,例如通过自定义 LifetimeManager 来实现注销等等.在作者看来,这些其实都不是根本的解决办法.因为服务的注册/注销本身是一个容器级过程,当中会涉及到一些中间对象的创建/清理 (Dispose) 以及不同对象之间的协调,本应由容器来提供支持才…
很多 Ioc 框架在创建对象的过程中,都会采取某种方式来缓存/复用/释放已构建的对象.在 My.Ioc 中,这个目的是通过 Lifetime/ILifetimeScope 来实现的.其中,Lifetime 实现了缓存/复用对象的功能,ILifetimeScope 则实现了复用/释放对象的功能. My.Ioc 默认提供了三种 Lifetime:ContainerLifetime.TransientLifetime 和 ScopeLifetime.这里简单解释一下它们的含义:ContainerLif…
本文的目的在于通过一些示例,向大家说明 My.Ioc 支持哪些类型的依赖关系.也就是说,如何设计对象不会导致循环依赖. 在 Ioc 世界中,循环依赖是一个顽敌.这不仅因为它会导致 Ioc 容器抛出异常,而且还因为它是不可预知的,尽管通过仔细的配置是可以尽量避免这个问题的. 当我们在 Ioc 容器中注册对象时,我们事先并不知道该对象与其他对象之间的依赖关系,因为依赖关系是由 Ioc 容器管理的.这种依赖关系要等到我们首次调用 container.Resolve(contractType) 时才能确…