在使用 Ioc 框架时,一般我们建议集中在一个称为 Composition Root(其含义请参见下面的小注)的位置来注册 (Register) 和解析 (Resolve) 服务。这种做法的目的在于限制 Ioc 的使用场合,防止在应用程序中到处引用 Ioc 框架,从而尽量减少应用程序本身对于 Ioc 框架的依赖。

上述模式固然能够很好地解耦应用程序和 Ioc 框架,使我们能够在需要的时候方便地更换 Ioc 框架,但它同时也带来了一个问题:难道我们一定要在程序启动时注册所有服务吗?有些服务并不一定会马上用到,有一些服务甚至在整个应用程序运行过程中都可能不会用到。在这种情况下,如果仍然固守上述模式,在程序启动时将所有服务都注册到容器中,其结果无疑会减缓程序启动速度,同时增加内存消耗。

针对这个问题,我们在 My.Ioc 中给出了延迟注册的解决办法。它的原理其实很简单:当应用程序向 My.Ioc 容器请求某个服务时,如果此时该服务尚未注册,容器便会触发一个 ObjectBuilderRequested 事件,并在事件参数中提供所请求的契约类型 (Contract Type) 和注入点信息 (InjectionInfo),而订阅了该事件的处理程序 (Event Handler) 便可以在这个时候根据契约类型和注入点信息来决定是否向容器中注册相应的服务以满足应用程序需求。

用法很简单,示例代码如下:

using System;
using System.Diagnostics;
using My.Ioc; namespace LazyRegistration
{
public interface ILazyService
{ }
public class LazyService : ILazyService
{ } class Program
{
static bool _eventHandled = false; static void Main(string[] args)
{
IObjectContainer container = new ObjectContainer(false);
container.ObjectBuilderRequested += OnObjectBuilderRequested;
var lazy = container.Resolve<ILazyService>();
Debug.Assert(lazy != null);
Debug.Assert(lazy is LazyService); Console.WriteLine(_eventHandled);
Console.ReadLine();
} static void OnObjectBuilderRequested(ObjectBuilderRequestedEventArgs args)
{
if (args.ContractType == typeof (ILazyService))
{
args.Register<ILazyService, LazyService>();
_eventHandled = true;
}
}
}
}

 小注:

Composition Root 的定义是“一个组装应用程序各个模块的位置,一个应用程序中应该仅有一个这样的位置,这个位置应当尽量靠近应用程序入口点,在一般情况下它就是应用程序的入口点。例如,对于控制台应用程序来说,这个位置可能就是 Main 函数;对于 ASP.NET MVC 应用程序来说,这个位置可能是 global.asax;对于 WPF 应用程序来说,这个位置可能是 App.xaml...”。

源码可从此处下载。

My.Ioc 代码示例——利用 ObjectBuilderRequested 事件实现延迟注册的更多相关文章

  1. My.Ioc 代码示例——如何使用默认构造参数,以及如何覆盖默认构造参数

    在 Ioc 世界中,有些框架(例如 Autofac/NInject/Unity)支持传递默认参数,有些框架(例如 SimpleInjector/LightInjector 等)则不支持.作为 My.I ...

  2. My.Ioc 代码示例——使用观察者机制捕获注册项状态的变化

    在 My.Ioc 中,要想在服务注销/注册时获得通知,可以通过订阅 ObjectBuilderRegistered 和 ObjectBuilderUnregistering 这两个事件来实现.但是,使 ...

  3. My.Ioc 代码示例——属性和方法注入

    在 My.Ioc 中,我们可以指定让容器在构建好对象实例之后,自动为我们调用对象的公共方法或是为对象的公共属性赋值.在解析对象实例时,容器将根据我们在注册对象时指定的方法调用或属性赋值的先后顺序,调用 ...

  4. My.Ioc 代码示例——实现自动注册/解析

    在很多 Ioc 容器中,当使用者向容器请求实现了某个契约类型 (Contract Type) 的服务时 (调用类似如下方法 container.Resolve(Type contractType)), ...

  5. My.Ioc 代码示例——使用条件绑定和元数据(可选)构建插件树

    本文旨在通过创建一棵插件树来演示条件绑定和元数据的用法. 说“插件树”也许不大妥当,因为在一般观念中,谈到插件树,我们很容易会想到 Winform/Wpf 中的菜单.举例来说,如果要在 Winform ...

  6. My.Ioc 代码示例——谈一谈如何实现装饰器模式,兼谈如何扩展 My.Ioc

    装饰器模式体现了一种“组合优于继承”的思想.当我们要动态为对象增加新功能时,装饰器模式往往是我们的好帮手. 很多后期出现的 Ioc 容器都为装饰器模式提供了支持,比如说 Autofac.在 My.Io ...

  7. My.Ioc 代码示例——注册项的注销和更新

    当您需要从 Ioc 容器中注销/删除一个注册项的时候,您会怎么做呢? 有人曾经在 stackoverflow 上提问“如何从 Unity 中注销一个注册项”.对于这个问题,有人的回答是“有趣.你为什么 ...

  8. My.Ioc 代码示例——Lifetime 和 ILifetimeScope

    很多 Ioc 框架在创建对象的过程中,都会采取某种方式来缓存/复用/释放已构建的对象.在 My.Ioc 中,这个目的是通过 Lifetime/ILifetimeScope 来实现的.其中,Lifeti ...

  9. My.Ioc 代码示例——避免循环依赖

    本文的目的在于通过一些示例,向大家说明 My.Ioc 支持哪些类型的依赖关系.也就是说,如何设计对象不会导致循环依赖. 在 Ioc 世界中,循环依赖是一个顽敌.这不仅因为它会导致 Ioc 容器抛出异常 ...

随机推荐

  1. js 外部文件加载处理

    概述 前端在日常工作中很大一部分时间是在思考页面的优化方案,让页面载入得更快.鉴于javascript是单线程的事件驱动语言,优化工作之一就是:控制图片.swf.iframe等大流量文件以及js和cs ...

  2. 一个用UpdateLayeredWindow实现窗体半透明的delphi的代码

    http://www.pudn.com/downloads171/sourcecode/windows/detail791686.html unit Unit1; interface  uses   ...

  3. table 的边框变细

    table { border-width: 0px 0px 1px 1px; border-style:solid;border-color:black} td { border-width: 1px ...

  4. width:auto; 和 width:100%;的不同

    width:auto:会将元素撑开至整个父元素width,但是会减去子节点自己的margin,padding或者border的大小.width:100%:会强制将元素变成和父元素一样的宽,并且添加额外 ...

  5. js中的Call与apply方法

    看到同行写得不错,直接转载了...0.0  祝大家天天开心! 例子来源http://uule.iteye.com/blog/1158829

  6. Linux下的定时器:alarm()与setitimer()

    Linux下的定时器有两种,以下分别介绍: 1.alarm 如果不要求很精确的话,用alarm()和signal()就够了 unsigned int alarm(unsigned int second ...

  7. 【索引】用PS3手柄在安卓设备上玩游戏系列

    谈安卓游戏对手柄的支持:http://www.cnblogs.com/duxiuxing/p/3729802.html 连接手柄和设备:http://www.cnblogs.com/duxiuxing ...

  8. Windows Shell Extension 系列文章

    Windows Shell Extension 系列文章 http://www.codeproject.com/Articles/512956/NET-Shell-Extensions-Shell-C ...

  9. python 代码格式化工具:autopep8

    学习资料: https://github.com/hhatto/autopep8 背景 autopep8 会根据 PEP 8 样式文档来格式化 python 代码.它使用 pep8 来决定代码的哪部分 ...

  10. java MessageFormat 应用 和 疑惑

    先来个demo String string = "{0}\"{1}\""; System.out.println(MessageFormat.format(st ...