看了很多牛人关于Unity的文章后,深有感触
下面简单介绍下UnityContainer 怎么注册和生成具体类的对象
假设我们一个命名空间为UnityContainerText的项目中拥有一个接口和实现该接口的类
namespace
UnityContainerText
{
public
interface
ILogger
{
void
Writer();
}
}
public
class
DatabaseLogger:ILogger
{
public
void
Writer()
{
Console.WriteLine(
"
Hello! Unity
"
);
}
}
当然,工作开始前还要先导入Microsoft.Practices.Unity.Configuration.dll和Microsoft.Practices.Unity.dll
首先介绍的是硬编码的方式注册和获取类实例:如下图
代码
class
Program
{
static
void
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
>
<
type
type
=
"
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的一个简单应用。。
首先感谢许多牛人的帮助,我们要学的东东太多。。。大家努力吧