下面这段代码展示了 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. js 点名

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  2. 织梦DedeCMS子目录移动到根目录的方法

    有时候我们在子目录中安装了dedecms,但有时候需要将其换到根目录中,下面就讲一下织梦DedeCMS子目录移动到根目录的方法: 下面是具体的操作步骤,强烈建议先备份数据库. 1.进入dedecms后 ...

  3. JQuery Dialog(JS模态窗口,可拖拽的DIV) 效果实现代码

    效果图 调用示意图   交互示意图 如上图所示,这基本是JQueryDialog的完整逻辑流程了. 1.用户点击模态窗口的“提交”按钮时,调用JQueryDialog.Ok()函数,这个函数对应了用户 ...

  4. Delphi笔记(GL_Scene安装及简单使用)

    前一段时间,需要弄一个四轴的监控平台,看了匿名的上位机后,十分感兴趣.于是我也想自己也弄一个上位机来玩玩,在将串口通讯调好了以后,就开始好奇那个3D模型是怎么弄的.在网上面查找了很多资料,由于我用的是 ...

  5. light oj 1248 第六周E题(期望)

    E - 期望(经典问题) Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu   Descri ...

  6. AngularJs 【使用】 -- ng-repart 排序使用

    1.单字段 ng-repeat="item in dataList | orderBy:'field' " 2.多字段 ng-repeat="item in dataLi ...

  7. JS之路——字符串函数

    JS自带函数concat将两个或多个字符的文本组合起来,返回一个新的字符串.var a = "hello";var b = ",world";var c = a ...

  8. Hadoop 学习笔记(二) HDFS API

    4.删除HDFS上的文件 package proj; import java.io.IOException; import org.apache.hadoop.conf.Configuration; ...

  9. CSS3自定义图标

    http://ntesmailfetc.blog.163.com/blog/static/206287061201292631536545/ http://www.zhihu.com/question ...

  10. poj 3020Antenna Placement

    http://poj.org/problem?id=3020 #include<cstdio> #include<cstring> #include<algorithm& ...