[IOC] StructureMap的疑惑。

大家好。

StructureMap的一些简单应用(基本用法、自动装配、生命周期、延迟加载)。

Q:什么是IoC

IoC:Inversion of Control。中文名:控制反转。是一种思想、一种模式。控制权被反转。

例子:企业经理有一批商品要存入仓库,但是现在没有仓库,所以需要找一个仓库,然后将商品存入。

场景A:经理去找一座仓库。=>找仓库的控制权一直在主管手上,经理必须自己找。

场景B:经理告诉手下去找一座仓库。=>经理将找仓库的控制权交给手下。这种将控制权转移的过程就是Inversion of Control。

逻辑:(1)创建一个SqlServerHelper对象。(2)存入到SqlServer数据库中。

场景A:

class ProductManager{private readonly IDBHelper dbHelper;public ProductManager (){dbHelper = new SqlServerHelper ();}public void SaveProduct (Product product){dbHelper.Save (product);}}internal interface IDBHelper{void Save (Product product);}class SqlServerHelper : IDBHelper{public void Save (Product product){//Save in SqlServer}}

场景A:

1、创建SqlServerHelper的控制权在经理手里。

2、ProductManager与SqlServerHelper组件存在依赖。当依赖变化时,也就是更换SqlServerHelper组件的时候,我们需要改ProductManager代码。

3、当ProductManager调用端需要save到Oracle的时候。ProductManager代码无法复用。

4、给ProductManager添加测试。如果测试挂掉。无法确定问题是出在ProductManager还是SqlServerHelper(代码逻辑比较简单,这里不太明显)。(比如鼠标不Work了,不能确定到底是鼠标本身的问题,还是电脑USB的问题)

—————————————————————————————————————————————————————————————————————————–

场景B:

class ProductManager{private readonly IDBHelper dbHelper;public ProductManager (){dbHelper = Employee.Find ();}public void SaveProduct (Product product){dbHelper.Save (product);}}internal interface IDBHelper{void Save (Product product);}class SqlServerHelper : IDBHelper{public void Save (Product product){//Save in SqlServer}}static class Employee{public static SqlServerHelper Find (){return new SqlServerHelper ();}}

场景B:

1、创建组件的控制权由经理交给了第三方Employee。(控制权转移)

2、ProductManager与SqlServerHelper组件之间没有直接的依赖,而是通过第三方Employee去控制它们之间的依赖(松散耦合)。

3、ProductManager可复用。当ProductManager调用方需要存入Oralce的时候,只需要改变Employee中代码即可。(可复用)

4、组件相对独立、可以分别测试ProductManager组件和SqlServerHelper组件。(比如电脑中各个部件都需要独立的测试。测试通过后在组装一起)

这里并不是IoC的具体实现。可以将第三方Employee理解为一个容器。只需要知道把控制权转移到第三方是为了削弱ProductManager与SqlServerHelper的依赖即可。

那么为什么需要IoC就很清晰了:降低组件之间的耦合、提高软件可测试性、代码复用等。

—————————————————————————————————————————————————————————————————————————–

Q:怎么实现IoC?

IoC容器:一个负责组件管理的容器,可以在容器中注册组件,也可从容器中取出组件。

现在我们可以把Employee对象理解为一个容器。我们在这个容器里管理SqlServerHelper组件。

1、首先在容器里注册ProductManager的依赖组件SqlServerHelper(用一个XML文件当做容器)

<?xml version="1.0" encoding="utf-8" ?><configuration> <configSections><sectionname="StructureMap"type="StructureMap.Configuration.StructureMapConfigurationSection,StructureMap"/> </configSections> <StructureMap MementoStyle="Attribute"><DefaultInstancePluginType="IoC_SMTest.IDBHelper,IoC_SMTest"PluggedType="IoC_SMTest.SqlServerHelper,IoC_SMTest" /> </StructureMap></configuration>

PluginType:"IoC_SMTest.IDBHelper"IDBHelper为ProductManager下的接口。

pluggedType:"IoC_SMTest.SqlServerHelper"SqlServerHelper为IDBHelper的实现

此时容器里定义了:IDBHelper的实现是SqlServerHelper。(ProductManager所依赖的组件是SqlServerHelper)

2、获取该容器里的依赖关系

ObjectFactory.Initialize(x =>{x.PullConfigurationFromAppConfig = true;});

执行这步之后。程序把Config里定义的依赖关系pull下来,已经知道IDBHelper依赖SqlServerHelper组件

3、从容器中获取组件ObjectFactory.GetInstance<IDBHelper>();

在给产品代码加一个OracleDB。实现SqlServer和Oracle之间的切换。

class ProductManager{private readonly IDBHelper dbHelper;public ProductManager (){dbHelper = ObjectFactory.GetInstance<IDBHelper> ();}public void SaveProduct (Product product){dbHelper.Save (product);}}interface IDBHelper{void Save (Product product);}class SqlServerHelper : IDBHelper{public void Save (Product product){//Save in SqlServer}}class OracleHelper : IDBHelper{public void Save (Product product){//Save in Oracle}}不知道来年,会不会开出一地的记忆和忧愁。

[IOC] StructureMap的疑惑。

相关文章:

你感兴趣的文章:

标签云: