在很多 Ioc 容器中,当使用者向容器请求实现了某个契约类型 (Contract Type) 的服务时 (调用类似如下方法 container.Resolve(Type contractType)),如果该服务尚未注册,而且该契约类型符合某种约定,那么容器将会自动为将该契约类型创建一个注册项 (Registration),并将该注册项添加到容器中,然后使用该注册项创建一个服务实例并将其返回给使用者。
例如,在 asp.net 应用程序中,假设我们有这样一个约定“只要契约类型是具体引用类型(不是值类型/接口/抽象类型),而且派生自 Controller 类,框架便可将其自动注册到容器中”,那么我们就可以实现类似如下效果:
public class MyController : Controller { } // Create an instance of container var container = new ObjectContainer(true); var myController = container.Resolve<MyController>();
在上面的示例中,尽管 MyController 这个类型并未注册到容器,但由于它符合上述约定,因此容器可以自动为其构造一个对象实例并返回给调用者。实际上,这是一种称为“基于约定的配置/注册”的功能。通过这种功能,我们可以进一步减少与 Ioc 框架的耦合,同时可以更加灵活地配置要将哪些服务注册到容器中。
在 My.Ioc 中,我们通过自动注册规则 (IAutoRegistrationPolicy) 提供了类似的功能。请看下面的代码示例:
1 using System; 2 using System.Diagnostics; 3 using My.Ioc; 4 using My.Ioc.Core; 5 using My.Ioc.Exceptions; 6 using My.Ioc.Lifetimes; 7 8 namespace UnregisteredConcreteTypeResolution 9 { 10 public class AutoRegistrableClass 11 { 12 } 13 class CustomAutoRegistrationPolicy : IAutoRegistrationPolicy 14 { 15 #region IAutoRegistrationPolicy Member 16 17 public bool ShouldRegister(Type concreteType) 18 { 19 return concreteType == typeof(AutoRegistrableClass); 20 } 21 22 public ILifetimeProvider GetLifetimeProvider() 23 { 24 return new ContainerLifetimeProvider(); 25 } 26 27 #endregion 28 } 29 30 class Program 31 { 32 static void Main(string[] args) 33 { 34 IObjectContainer container = new ObjectContainer(false); 35 AutoRegistrableClass instance; 36 try 37 { 38 instance = container.Resolve<AutoRegistrableClass>(); 39 } 40 catch (Exception ex) 41 { 42 Debug.Assert(ex is ObjectBuilderNotFoundException); 43 } 44 45 var option = new ContainerOption(false, new CustomAutoRegistrationPolicy()); 46 container = new ObjectContainer(option); 47 48 instance = container.Resolve<AutoRegistrableClass>(); 49 Debug.Assert(instance != null); 50 51 var instance2 = container.Resolve<AutoRegistrableClass>(); 52 Debug.Assert(instance2 != null); 53 Debug.Assert(instance == instance2); 54 55 Console.ReadLine(); 56 } 57 } 58 }
在上述示例中,如果我们不显式指定自动注册规则 (IAutoRegistrationPolicy),容器默认不会提供自动注册/解析功能,因此,当我们运行到上述代码的第 38 行时,程序便会抛出异常。但当我们另外创建一个容器实例,并通过构造参数将自动注册规则 CustomAutoRegistrationPolicy 传递到新容器实例中之后,这时再来运行 instance = container.Resolve<AutoRegistrableClass>() 这行,便不会再出现异常了。
本文源码可从此处下载。