概述
Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入。Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问题。构建一个成功应用程序的关键是实现非常松散的耦合设计。松散耦合的应用程序更灵活,更易于维护。这样的程序也更容易在开发期间进行测试。你可以模拟对象,具有较强的具体依赖关系的垫片(轻量级模拟实现),如数据库连接,网络连接,ERP连接,和丰富的用户界面组件。例如,处理客户信息的对象可能依赖于其他对象访问的数据存储,验证信息,并检查该用户是否被授权执行更新。依赖注入技术,可确保客户类正确实例化和填充所有这些对象,尤其是在依赖可能是抽象的 。
Unity 配置文件的完整格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
<?xml version= "1.0" encoding= "utf-8" ?> <configuration> <configSections> <section name= "unity" type= "Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration, Version=1.0.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </configSections> <unity> <typeAliases> <typeAlias alias= "singleton" type= "Microsoft.Practices.Unity.ContainerControlledLifetimeManager,Microsoft.Practices.Unity" /> <typeAlias alias= "external" type= "Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity" /> <typeAlias alias= "IMyInterface" type= "MyApplication.MyTypes.MyInterface, MyApplication.MyTypes" /> <typeAlias alias= "MyRealObject" type= "MyApplication.MyTypes.MyRealObject, MyApplication.MyTypes" /> <typeAlias alias= "IMyService" type= "MyApplication.MyTypes.MyService, MyApplication.MyTypes" /> <typeAlias alias= "MyDataService" type= "MyApplication.MyTypes.MyDataService, MyApplication.MyTypes" /> <typeAlias alias= "MyCustomLifetime" type= "MyApplication.MyLifetimeManager, MyApplication.MyTypes" /> </typeAliases> <containers> <container name= "containerOne" > <types> <type type= "Custom.MyBaseClass" mapTo= "Custom.MyConcreteClass" /> <type type= "IMyInterface" mapTo= "MyRealObject" name= "MyMapping" /> <type type= "Custom.MyBaseClass" mapTo= "Custom.MyConcreteClass" > <lifetime type= "singleton" /> </type> <type type= "IMyInterface" mapTo= "MyRealObject" name= "RealObject" > <lifetime type= "external" /> </type> <type type= "Custom.MyBaseClass" mapTo= "Custom.MyConcreteClass" > <lifetime value= "sessionKey" type= "MyApplication.MyTypes.MyLifetimeManager,MyApplication.MyTypes" /> </type> <type type= "IMyInterface" mapTo= "MyRealObject" name= "CustomSession" > <lifetime type= "MyCustomLifetime" value= "ReverseKey" typeConverter= "MyApplication.MyTypes.MyTypeConverter,MyApplication.MyTypes" /> </type> <type type= "IMyService" mapTo= "MyDataService" name= "DataService" > <typeConfig extensionType= "Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration" > <constructor> <param name= "connectionString" parameterType= "string" > <value value= "AdventureWorks" /> </param> <param name= "logger" parameterType= "ILogger" > <dependency /> </param> (车延禄) </constructor> <property name= "Logger" propertyType= "ILogger" /> <method name= "Initialize" > <param name= "connectionString" parameterType= "string" > <value value= "contoso" /> </param> <param name= "dataService" parameterType= "IMyService" > <dependency /> </param> </method> </typeConfig> </type> </types> <instances> <add name= "MyInstance1" type= "System.String" value= "Some value" /> <add name= "MyInstance2" type= "System.DateTime" value= "2008-02-05T17:50:00" /> </instances> <extensions> <add type= "MyApp.MyExtensions.SpecialOne" /> </extensions> <extensionConfig> <add name= "MyExtensionConfigHandler" type= "MyApp.MyExtensions.SpecialOne.ConfigHandler" /> </extensionConfig> </container> </containers> </unity> </configuration> |
unity的设计图
Unity的配置节的名称为”Unity",节处理程序的类型为 Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,它包含在程序集 Microsoft.Practices.Unity.Configuration 中。所在应当在网站是添加该程序集的引用。
unity 的子元素包含了一个 containers 元素,containers 元素可以包含若干个 container 元素。container 元素就是每个容器的配置,它有一个可选的 name 属性,用于指定容器的名称。
<types> 元素是 container 元素的子元素之一。包含任意数量的 type元素,用以添加类型注册,这些配置被container.RegisterType<TFrom,TTo>()注册;
type元素的属性。
name:在注册此类型时使用的名称。此属性是可选的,如果不指定此属性,所在的 add 元素即为默认的类型映射。
type:容器中配置的源类型。如果这是映射注册,这就是映射的起始对象的类型;如果这是单件注册,这就是对象的类型。此属性是必须的。
mapTo:类型映射的目标类型。如果这是映射注册,这就是映射的目标对象的类型。此属性是可选的。
lifetime:设置用于给定的类型和名称的生命周期。是一个来自 LifetimeStyle 枚举的值。有效的值是 Transient(默认),它导致了容器每次都创建一个新的实例;以及 Singleton,它使容器为每个请求返回同一实例。如果在配置一个单件时同时指定了 type 和 mapto 属性,SetSingleton 方法将返回指定在 mapTo 属性中的类型。如果 mapTo 属性没有指定值,SetSingleton 方法将返回指定在 type 属性中的类型。
<instances> 元素保持了用于此容器的已有对象实例的列表。这些对象被用容器的 RegisterInstance 方法进行注册。instances 元素包含了一系列添加单个实例的 add 元素。
add 元素的属性。
name:注册此实例时使用的名称。此属性是可选的。
type:此实例的类型。此属性是可选的。如果忽略,假定的类型是 System.String。
value:用于初始化实例的值。此属性是必须的。
typeConverter:用以转换提供的值到实例的匹配类型的类型转换器。如果没有指定,将使用指定类型的默认转换器。此属性是可选的。
<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,Microsoft.Practices.Unity.Configuration">
用来配置在类型注册时,构造函数依赖注入,属性依赖注入和方法依赖注入时的对象初始化信息。它包含以下几个子元素:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<constructor> <param name= "connectionString" parameterType= "string" > <value value= "AdventureWorks" /> </param> <param name= "logger" parameterType= "ILogger" > <dependency /> </param> </constructor> <property name= "Logger" propertyType= "ILogger" /> <method name= "Initialize" > <param name= "connectionString" parameterType= "string" > <value value= "contoso" /> </param> <param name= "dataService" parameterType= "IMyService" > <dependency /> </param> </method> |
在执行Container.Resolve()生成对象实例的时候,会根据上面的配置信息的内容对要生成的对象进行依赖注入。
二、加载配置信息到容器中
1、加载一个单独的未命名容器或规定了默认容器:
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(container);
这样就会根据配置文件中的配置信息,在UnityContainer容器中注册类型映射
2、加载一个特殊命名容器的配置信息,需要使用定义在配置文件中的容器名,而不是引用默认容器。例如,如果在配置中有一个命名为containerOne的容器,能使用如下代码初始化并加载它:
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers["containerOne"].Configure(container);
3、为了从配置信息中创建一个嵌套容器继承, 可以简单的使用CreateChildContainer方法在你需要的继承深度中创建容器对象,然后通过读取各自的配置文件加载合适的配置。下面的代码展示了如何从配置文件中实例化和加载两个容器,这个配置文件同时包含了针对两个命名为containerOne和newstedChildContainer容器的注册信息,类型映射和扩展定义。
IUnityContainer parentContainer = new UnityContainer();
IUnityContainer childContainer = parentContainer.CreateChildContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers["containerOne"].GetConfigCommand().Configure(parentContainer);
section.Containers["nestedChildContainer"].Configure(childContainer);
API
UnityContainer.RegisterType<ITFrom,TTO>();
UnityContainer.RegisterType< ITFrom, TTO >();
UnityContainer.RegisterType< ITFrom, TTO >("keyName");
IEnumerable<T> databases = UnityContainer.ResolveAll<T>();
IT instance = UnityContainer.Resolve<IT>();
T instance = UnityContainer.Resolve<T>("keyName");
UnitContainer.RegisterInstance<T>("keyName",new T());
UnityContainer.BuildUp(existingInstance);
IUnityContainer childContainer1 = parentContainer.CreateChildContainer();
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public abstract class SQLHelp { public abstract string SqlConnection(); } public class MySqlHelp:SQLHelp { public override string SqlConnection() |