下面这段代码展示了 My.Ioc 的基本用法:

 using System;
using System.Collections.Generic; namespace My.Ioc.Sample
{
public interface IConcurrency
{
int Code { get; }
} public interface IConcurrencyService
{
string Name { get; }
void AddConcurrency(IConcurrency concurrency);
void RemoveConcurrency(IConcurrency concurrency);
} public class ConcurrencyService : IConcurrencyService
{
readonly Dictionary<int, IConcurrency> _concurrencies = new Dictionary<int, IConcurrency>(); public string Name
{
get { return GetType().Name; }
} public void AddConcurrency(IConcurrency concurrency)
{
_concurrencies.Add(concurrency.Code, concurrency);
} public void RemoveConcurrency(IConcurrency concurrency)
{
_concurrencies.Remove(concurrency.Code);
}
} public class NewConcurrencyService : IConcurrencyService
{
#region IConcurrencyService Members public string Name
{
get { return GetType().Name; }
} public void AddConcurrency(IConcurrency concurrency)
{
throw new NotImplementedException();
} public void RemoveConcurrency(IConcurrency concurrency)
{
throw new NotImplementedException();
} #endregion
} public interface ISimpleConsumer
{
IConcurrencyService ConcurrencyService { get; }
} public class SimpleConsumer : ISimpleConsumer
{
readonly IConcurrencyService _concurrencyService; public SimpleConsumer(IConcurrencyService concurrencyService)
{
_concurrencyService = concurrencyService;
} public IConcurrencyService ConcurrencyService
{
get { return _concurrencyService; }
}
} public interface IComplexConsumer : IDisposable
{
IConcurrencyService ConcurrencyService { get; }
} public class ComplexConsumer : IComplexConsumer
{
readonly string _name;
readonly IConcurrencyService _concurrencyService; public ComplexConsumer(string name, IConcurrencyService concurrencyService)
{
_name = name;
_concurrencyService = concurrencyService;
} public IConcurrencyService ConcurrencyService
{
get { return _concurrencyService; }
} public string Name
{
get { return _name; }
} public string Address { get; set; } public void Print()
{
Console.WriteLine(_name + " who lives in " + (Address ?? "Fujian") + " is using the service " + _concurrencyService.Name);
} public void Dispose()
{
Console.WriteLine("ComplexConsumer is disposing...");
}
} class Program
{
static IObjectRegistration _concurrencyServiceRegistration;
static IObjectObserver<ISimpleConsumer> _simpleConsumerObserver; static void Main(string[] args)
{
// First, we need to create an instance of IObjectContainer.
IObjectContainer container = new ObjectContainer(true); // Then, we register some services
container.Register<IConcurrencyService, ConcurrencyService>()
.WhenParentTypeIsAny(typeof(SimpleConsumer), typeof(ComplexConsumer))
.In(Lifetime.Container())
.Set("ConcurrencyService")
.Return(out _concurrencyServiceRegistration); container.Register<ISimpleConsumer, SimpleConsumer>(); var consumerName = Parameter.Positional("Johnny.Liu");
container.Register<IComplexConsumer, ComplexConsumer>()
.WithConstructor(consumerName)
.WithPropertyValue("Address", "Fujian")
.WithMethod("Print")
.In(Lifetime.Transient()); // Finally, don't forget to commit the registrations to the registry.
container.CommitRegistrations(); // Now you can ask the container to build instances for you.
var simpleConsumer1 = container.Resolve<ISimpleConsumer>(); if (!container.TryGetObserver(out _simpleConsumerObserver))
throw new Exception();
_simpleConsumerObserver.Changed += OnObjectBuilderChanged;
var simpleConsumer2 = container.Resolve(_simpleConsumerObserver); using (var scope = container.BeginLifetimeScope())
{
var complexConsumer = scope.Resolve<IComplexConsumer>();
} // At last, we will unregister the current concurrency service to let the other concurrency
// service implementations to have a chance to replace it.
container.Unregister(_concurrencyServiceRegistration);
container.Register(typeof(IConcurrencyService), typeof(NewConcurrencyService));
// As we said, don't forget to commit the registrations to the registry.
container.CommitRegistrations(); using (var scope = container.BeginLifetimeScope())
{
var complexConsumer = scope.Resolve<IComplexConsumer>();
} Console.ReadLine();
} static void OnObjectBuilderChanged(ObjectBuilderChangedEventArgs args)
{
Console.WriteLine(args.ChangeMode);
}
}
}

用法比较简单,跟大家熟悉的大多数 Ioc 容器差不多。我们这里来逐句解释一下:

IObjectContainer container = new ObjectContainer(true);

这一句创建了一个 ObjectContainer 对象。构造参数 true 表示容器默认将采用 Emit(动态生成代码)方式来构建对象。

container.Register<IConcurrencyService, ConcurrencyService>()
.WhenParentTypeIsAny(typeof(SimpleConsumer), typeof(ComplexConsumer))
.In(Lifetime.Container())
.Set("ConcurrencyService")
.Return(out _concurrencyServiceRegistration);

Register 方法将一个 ConcurrencyService 实现绑定到 IConcurrencyService 契约。WhenParentTypeIsAny 方法指定该服务只能用于 SimpleConsumer 或 ComplexConsumer 类。因此,如果您稍后在解析时写上以下这句:

var concurrencyService = container.Resolve<IConcurrencyService>();

则会收到一个 InvalidObjectBuilderException 错误,因为我们在上面的配置中已经指定了 IConcurrencyService 这个服务只能在构造 SimpleConsumer 或 ComplexConsumer 实例时由相应的 ObjectBuilder 向容器请求。

In 方法指定该服务注册项的生命周期,这里使用的是 Container 生命周期,即注册项的生命周期将同容器一样长,而且每次向容器请求该服务时,返回的都是相同的实例。也就是说,这是一个单例对象。Set 方法表明附加一个元数据 ("ConcurrencyService") 到该服务注册项中。Return 方法返回一个 IObjectRegistration 对象。该对象可以作为一个存根,用于在不再需要该服务的时候注销该服务。同时,它也可用于解析服务对象(调用 container.Resolve(IObjectRegistration registration) 方法重载),而不必像调用 container.Resolve(Type contractType) 时一样每次都从注册表中检索服务。

var consumerName = Parameter.Positional("Johnny.Liu");
container.Register<IComplexConsumer, ComplexConsumer>()
.WithConstructor(consumerName)
.WithPropertyValue("Address", "Fujian")
.WithMethod("Print")
.In(Lifetime.Transient());

上面这句代码指定将 ComplexConsumer 绑定到 IComplexConsumer,同时我们注意到这里还提供了一个默认构造参数。在这里,这个构造参数是必需的,因为 ComplexConsumer 构造函数的签名是:

public ComplexConsumer(string name, IConcurrencyService concurrencyService)

我们看到这个构造函数的第一个参数是 string 类型,在 My.Ioc 中这种类型的参数是不可自动装配的 (non-autowirable),用户必须为不可自动装配的依赖项提供一个默认值(不可自动装配的类型包括:所有值类型 + string + Type)。

WithPropertyValue 方法和 WithMethod 方法告诉容器,在构建好 ComplexConsumer 对象后,立即将该对象的 Address 属性赋值为“Fujian”,并调用该对象的“Print”方法。

配置(注册)好所有服务之后,此时这些服务并没有添加到注册表,而是被缓存到一个 RegistrationCommitter 中,因此我们需要显式调用下面这句代码将所有注册项提交到注册表中:

container.CommitRegistrations();

经过上面的配置,我们终于可以让容器为我们构建对象实例了。

var simpleConsumer1 = container.Resolve<ISimpleConsumer>();

这句正是向容器请求返回一个实现 ISimpleConsumer 接口的对象。

除了直接向容器请求对象之外,我们还可以向容器请求返回一个 IObjectObserver/IObjectCollectionObserver 对象,并通过该对象来解析服务实例,如下所示:

if (!container.TryGetObserver(out _simpleConsumerObserver))
throw new Exception();
_simpleConsumerObserver.Changed += OnObjectBuilderChanged;
var simpleConsumer2 = container.Resolve(_simpleConsumerObserver);

这样做的好处是,当该对象 (SimpleConsumer) 依赖的其他子对象(这里是 IConcurrencyService 对象)注册/注销/激活/停用时, Observer 对象将会收到通知(需要订阅该 Observer 对象的 Changed 事件)。此外,IObjectObserver 和 IObjectCollectionObserver 对象与 IObjectRegistration 对象一样,也可以直接用于解析服务对象,而不必每次都向注册表检索服务,从而可以提高性能。

IComplexConsumer 对象的解析与 ISimpleConsumer 有点不一样,我们看下面这段代码:

using (var scope = container.BeginLifetimeScope())
{
var complexConsumer = scope.Resolve<IComplexConsumer>();
}

这里,我们首先向容器请求获取一个 ILifetimeScope 对象,然后使用该对象来解析 IComplexConsumer 对象。这是因为 IComplexConsumer 实现了 IDisposable 接口,这表明该对象在使用完之后需要清理资源。在 My.Ioc 框架中,解析任何实现了 IDisposable 接口的对象时都需要先申请一个 ILifetimeScope,因为对象资源的清理是通过 ILifetimeScope 来完成的。ILifetimeScope 类似于我们通常所说的“变量作用域”的概念,但它还实现了对象共享的功能,关于这个话题我们还会在以后的文章中加以介绍,这里不再赘言。

使用完毕之后,我们可以将不再需要的服务注册项注销,如下所示:

container.Unregister(_concurrencyServiceRegistration);

运行这句之后,_simpleConsumerObserver 将被停用,而无法再用于解析服务对象,因为其依赖的服务 (IConcurrencyService) 已被注销。同时 OnObjectBuilderChanged 方法也会收到相应通知。不仅 ISimpleConsumer,此时所有直接和间接依赖于 IConcurrencyService 的服务都将被停用,而无法用于解析服务对象。如果我们想要让这些服务再次恢复功能,可以再注册一个实现了 IConcurrencyService 契约的服务并将其注册到容器中,如下代码所示:

container.Register(typeof(IConcurrencyService), typeof(NewConcurrencyService));
container.CommitRegistrations();

这样,那些依赖于 IConcurrencyService 契约的服务都将恢复功能。我们来再次运行下面的代码看一看:

using (var scope = container.BeginLifetimeScope())
{
var complexConsumer = scope.Resolve<IComplexConsumer>();
}

如无意外,运行上面这段代码,控制台将会输出:

"Johnny.Liu who lives in Fujian is using the service NewConcurrencyService"
"ComplexConsumer is disposing..."

表明我们的新 NewConcurrencyService 服务已取代了原来的 ConcurrencyService 并正常工作,且 ComplexConsumer 对象在超出作用域后已被清理。

总结

上面,我们简单地介绍了 My.Ioc 的使用方法。由于篇幅的缘故,很多问题并未谈及,我们将在以后的文章中逐一向大家介绍。

简要介绍 My.Ioc 的用法的更多相关文章

  1. Windows ToolTips简要介绍(转)

    原文转自 https://blog.csdn.net/sesiria/article/details/77450151 Windows 标准控件ToolTips简要介绍 参考文档 MSDN https ...

  2. 0-Broadcast机制原理简要介绍

    Broadcast机制简要介绍 来源: http://blog.csdn.net/luoshengyang/article/details/6730748 导语 广播机制在Android系统中,也不算 ...

  3. Android Debuggerd 简要介绍和源码分析(转载)

    转载: http://dylangao.com/2014/05/16/android-debuggerd-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%92%8C%E ...

  4. 简要介绍BASE64、MD5、SHA、HMAC几种方法。

    加密解密,曾经是我一个毕业设计的重要组件.在工作了多年以后回想当时那个加密.解密算法,实在是太单纯了.     言归正传,这里我们主要描述Java已经实现的一些加密解密算法,最后介绍数字证书.     ...

  5. [转]Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划

    转自:Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划 前面我们从Android应用程序与SurfaceFlinger服务的关系出发,从侧面简单学习了Surfa ...

  6. [转] Android资源管理框架(Asset Manager)简要介绍和学习计划

    转自:http://blog.csdn.net/luoshengyang/article/details/8738877 Android应用程序主要由两部分内容组成:代码和资源.资源主要就是指那些与U ...

  7. C++ Iterator迭代器介绍及Iterator迭代器用法代码举例

    C++ Iterator迭代器介绍 迭代器可被用来访问一个容器类的所包函的全部元素,其行为像一个指针.举一个例子,你可用一个迭代器来实现对vector容器中所含元素的遍历.有这么几种迭代器如下: 迭代 ...

  8. Activity启动过程简要介绍

    无论是通过点击应用程序图标来启动Activity,还是通过Activity内部调用startActivity接口来启动新的Activity,都要借助于应用程序框架层的ActivityManagerSe ...

  9. Android应用程序的Activity启动过程简要介绍和学习计划

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6685853 在Android系统中,Activ ...

随机推荐

  1. 初涉JavaScript模式 (8) : 函数 【概述】

    什么是函数 函数,是一个大型程序中的某部份代码,由一个或多个语句块组成.它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性.(维基百科) 函数的特点 第一类对象 在JavaScript世界中 ...

  2. 解决WebService本地访问正常,远程无法访问的问题

    发布webservice后部署到自己的服务器上,然后本机,外网远程访问都没事,在用户服务器上部署后只能本机访问,远端访问不了,通过网络搜索到下面方法,但改后仍然不行.原来在自己服务器部署时是在默认网站 ...

  3. mysql的sql优化案例

    前言 mysql的sql优化器比较弱,选择执行计划貌似很随机. 案例 一.表结构说明mysql> show create table table_order\G***************** ...

  4. The underlying provider failed on Open. EF

    本地测试是可以的:但是放到服务器上就不行了: 报错:"The underlying provider failed on Open." 这一情况和我以前遇上的一次错误有点相似啊:都 ...

  5. wxpython线程安全的方法

    wx中实现了3个线程安全的函数.如果在线程中,直接访问并更新主线程的UI,会遇到问题,有时候阻塞UI或者更新不起作用,有时严重的话会引起python崩溃. 三个安全线程如下: wx.PostEvent ...

  6. PYTHON WEATHER

    小玩一下python强大的库文件,调api获取天气情况 #coding:utf-8 import urllib import json content = urllib.urlopen('http:/ ...

  7. chrome代理服务器设置

    在百度的内网很难访问chrome的相关站点,如果安装一些chrome的插件很不方便,所以呢,研究了一下chrome浏览器的代理模式,FQ安装插件. Chrome设置代理服务器的方法大体有几种: 1. ...

  8. Android 判断当前网络连接类型

    实际应用开发时,如果存在需要用户获取大量数据的情况,最好是先判断下网络类型,提示用户当前的网络类型,是否需要连接Wifi,etc.(手机流量太贵啦,当然土豪是无视这玩意的, (/ □ \)). 定义网 ...

  9. IIS 内部运行机制及Asp.Net执行过程详解

    一直以来对一个Asp.net页面穿过IIS后就返回给浏览器一个HTML页面感觉很是神奇.虽然做技术这么长时间了,也曾经大致了解过一点来龙去脉,但是如果你真的问起我比较详细的过程,我还真的回答不上来,好 ...

  10. MVC4 教程

    http://blog.csdn.net/huangjihua0402/article/details/8507055 http://www.cnblogs.com/lc-chenlong/p/324 ...