关于微软企业库中依赖注入容器Unity两种生成对象的实现

看了很多牛人关于Unity的文章后,深有感触

 

下面简单介绍下UnityContainer 怎么注册和生成具体类的对象

 

假设我们一个命名空间为UnityContainerText的项目中拥有一个接口和实现该接口的类

 

namespace UnityContainerText
{
publicinterface ILogger
{
void Writer();
}
}

 

publicclass DatabaseLogger:ILogger
{


publicvoid Writer()
{
Console.WriteLine(
"Hello! Unity");
}


}

 

当然,工作开始前还要先导入Microsoft.Practices.Unity.Configuration.dllMicrosoft.Practices.Unity.dll

 

首先介绍的是硬编码的方式注册和获取类实例:如下图

 

 

代码
class Program
{
staticvoid Main(string[] args)
{
IUnityContainer container
=new UnityContainer();
container.RegisterType
<ILogger, DatabaseLogger>() ;
ILogger logger
= container.Resolve<ILogger>();
logger.Writer();
Console.ReadLine();
}
}

 首先创建UnItyContainer对象container,并且通过container.RegisterType<接口,实现接口的类>()方法

 实现了从ILogger到DatabaseLogger的映射,从而使用container.Resolve<ILogger>()或者container.Resolve(typeof(ILogger))

的方法取得了DatabaseLogger类的对象

 

聪明的你可能立马看到了这种硬编码方式的不足,就是不断的添加,导致产生高耦合的情况

 

 利用WEBCONFIG配置文件可以解决上述问题

 

 

在说配置文件前,先让大家看下UnIty在webconfig的结构图

 

 

 

 

 

代码
<configSections>
<section name="unity"type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<sectionGroup name="system.web.extensions"type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<sectionGroup name="scripting"type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="scriptResourceHandler"type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices"type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="jsonSerialization"type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
<section name="profileService"type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
<section name="authenticationService"type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
<section name="roleService"type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
</sectionGroup>
</sectionGroup>
</sectionGroup>
</configSections>
<appSettings/>
<connectionStrings/>
<unity>
<typeAliases>
<typeAliase alias="IFileLogger"type="UnityContainerText.ILogger,UnityContainerText">
</typeAliase>
</typeAliases>
<containers>
<container>
<types>
<typetype="UnityContainerText.ILogger,UnityContainerText" mapTo="UnityContainerText.DatabaseLogger"></type>
</types>
</container>
</containers>
</unity>

 

如上图:

Unity的配置都在Unity节点下

typeAliases是配置类型别名的,在typeAliases中配置的类型可以直接在contaniners使用,当在containers中使用时

就不需要填写完整的类型了,只需填在typeAliases注册的别名就可以了。当然也可以直接在container中注册完整的类型。

typeAlias 中alias是别名称,type 是类型。

containners节点中可以包含多个container,同时一个container中可以嵌套多个container了。

name:在注册此类型时使用的名称。此属性是可选的,如果不指定此属性,所在的 add 元素即为默认的类型映射。
type:容器中配置的源类型。如果这是映射注册,这就是映射的起始对象的类型;如果这是单件注册,这就是对象的类型。此属性是必须的。
mapTo:类型映射的目标类型。如果这是映射注册,这就是映射的目标对象的类型。此属性是可选的。

 

 

准备工作完成后开始代码实现

 

代码
static void Main(string[] args)
{

IUnityContainer container
= new UnityContainer();
UnityConfigurationSection section
= ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
section
.Containers.Default.Configure(container);
ILogger logger
= container.Resolve<ILogger>("databaseLogger");
logger
.Writer();
Console
.ReadLine();
}

 

 

第二行中的 UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;

这个是通过配置文件中<configSections>标签内的<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
获得<unity>标签下的内容

 

第三行:  section.Containers.Default.Configure(container);这样就会根据配置文件的配置,向容器中注册类型的映射;

如果配置中有多个容器,如果只是想加载某个的话,可以指定加载:section.Containers["ctrOne"].Configure(container); 

 

 随后 ILogger logger = container.Resolve<ILogger>("databaseLogger");

 便可以直接加载出对象了,而不需要先加载一堆诸如container.register().....的方法了,这样大大降低了代码的耦合

 

补充下:unity 容器可以实现子容器,也就是当父容器释放的时候,子容器也释放,但是子容器释放不影响父容器的使用

UnityContainer container = parentContainer.CreateChildContainer();

如图所示

 

 

 

 

这就是Unity的一个简单应用。。

 

 

 

首先感谢许多牛人的帮助,我们要学的东东太多。。。大家努力吧

 

 

posted @ 2010-08-12 14:15  逆时针の风  阅读(954)  评论(0编辑  收藏  举报