下面这段代码展示了 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. java判断网络连接是否正常

    /** * 判断本机当前的网络状态是否联通 * 在这里主要用到中国天气信息,所以访问百度地址是否能够访问成功来判断当前的网络状态 */ public static boolean isConnect( ...

  2. OOCSS学习(一)

    OOCSS —— 面向对象CSS 搜集一些该搜集的,然后汇总一下. 1.OOCSS 概念篇: 1)什么是面向对象 确定“对象”,并给这个对象创建CSS样式规则. 2)面向对象的CSS理论 OOCSS最 ...

  3. 超级易使用的jquery视频背景插件Vide

    http://www.jqcool.net/demo/201410/jquery-vide/ 官网: http://vodkabears.github.io/vide/

  4. PHP引用(&)详解

    PHP的引用(就是变量.函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的名字访问同一个变量内容. 变量的引用 PHP 的引用允许你用两个变量来指向同一个内容 //打印数组 fun ...

  5. 清橙A1484

    http://www.tsinsen.com/ViewGProblem.page?gpid=A1484### 题解: 在线插入并不好做,我们将所有操作离线,变为删除操作. 每次询问的时候对于当前B串所 ...

  6. ISO7816 传输协议 T0 T1

    T=0协议不能用一条命令来实现,必须分为两步实现:第一条命令为卡片提供数据,然后用另外一条相关的命令来取回数据.这样给卡片的编程带来很大麻烦,同时卡片内存中必须保留上一次操作需要返回的数据.这时如果不 ...

  7. SlidingMenu和ActionBarSherlock结合滑动式菜单都

    https://github.com/jfeinstein10/SlidingMenu http://actionbarsherlock.com/ SlidingMenu 的demo工程引用了Acti ...

  8. Java ClassLoader基础及加载不同依赖 Jar 中的公共类(转)

    http://www.iteye.com/topic/1135259 http://www.trinea.cn/android/java-loader-common-class/ http://www ...

  9. scheme lambda表达式 形参

     lambda表达式 (Lambda (arg1 …) exp1 exp2)从演算来看,(let ((var value) …) exp1 exp2…) == ((lambda (var …) exp ...

  10. 关于pthread里面一些函数的使用心得!

    第一次使用pthread,遇到的问题还真不少,现在我一一记录一下: 1.关于编译时出现 对‘pthread_create’未定义的引用 之类的错误的解决:由于pthread库不是Linux系统默认的库 ...