博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
微软企业库Unity学习笔记(二)
阅读量:4960 次
发布时间:2019-06-12

本文共 9139 字,大约阅读时间需要 30 分钟。

接下来介绍一下依赖注入的方式:

  1. 构造函数注入
  2. 属性注入
  3. 方法注入

2011041616554893.jpg

一、 构造函数注入

我们将介绍单构造函数和多构造函数注入

1) 单构造函数使用自动注入

  • 单构造函数自动注入,这里我们使用一个简单的例子具体类MyObject依赖于具体类MyDependentClass。
 
///
/具体类型的依赖关系
public
class
MyOjbect
{
private
string
description;
public
string
Description
{
get
{
return
description; }
set
{ description
=
value; }
}
public
MyOjbect(MyDependentClass myDependent)
{
this
.Description
=
myDependent.Description;
}
}
 
///
/注入依赖
MyOjbect objlist
=
container.Resolve
<
MyOjbect
>
();
  • 当然除了具体类型我们还可以使用接口或者基类类型作为参数注入依赖,这里我们定义一个接口和一个抽象类。
 
///
/ MyServiceBase是一个抽象类,然后objIMyService继承于该抽象类
///
/ IMyService是一个接口,objMyService实现该接口
public
class
MyOjbect
{
private
string
description;
public
string
Description
{
get
{
return
description; }
set
{ description
=
value; }
}
public
MyOjbect(MyServiceBase objIMyService, IMyService objMyService)
{
///
/TODO:
}
}
 
///
/注册抽象类和接口的映射关系
container.RegisterType
<
IMyService, MyServiceDependent
>
();
container.RegisterType
<
MyServiceBase, DataService
>
();
MyOjbect objlist
=
container.Resolve
<
MyOjbect
>
();

 

 

2) 多重载构造函数通过属性指定注入构造函数  

  通过InjectionConstructor属性指定要注入构造函数,和单构造函数功能一样,但要注意一点是当有多重载构造函数,如果我们没有使用属性指定注入构造函数,Unity会根据构造函数参数最多的进行依赖注入,如果不存在唯一最多参数的构造函数(例如:有两个或者两个以上构造函数具有最多参数时候),Unity会抛出异常。

 
public
class
MyOjbect
{
private
string
description;
public
string
Description
{
get
{
return
description; }
set
{ description
=
value; }
}
public
MyOjbect(MyServiceBase objIMyService)
{
///
/
}
[InjectionConstructor]
public
MyOjbect(MyServiceBase objIMyService, IMyService objMyService)
{
///
/
}
}

  

  通过前面的介绍我们初步明白了Unity的作用就是给我们一个更方便实现类与类的解耦,假设在一般情况一个类依赖于其他类的时候,我们必须实例化该依赖类,然后把实例传递给我们要调用类,但有了Unity它帮我们实例了这些。OK接下来讲一个具体例子。

2011041617025470.jpg

 
///
<summary>
///
父母类
 
///
</summary>
public
class
Parent
{
private
readonly
ChildA _classA;
private
readonly
ChildB _classB;
public
Parent() { }
//
指定依赖注入构造函数
[InjectionConstructor]
public
Parent(ChildA chA, ChildB chB)
{
this
._classA
=
chA;
this
._classB
=
chB;
}
public
override
string
ToString()
{
//
年长的父母依赖与孩子。
return
string
.Format(
"
The elder depend on {0} and {1}.
"
,
this
._classA.ToString(),
this
._classB.ToString());
}
}
///
<summary>
///
孩子类
///
</summary>
public
class
ChildA : Parent
{
public
override
string
ToString()
{
return
"
ChildA
"
;
}
}
///
<summary>
///
孩子类
///
</summary>
public
class
ChildB : Parent
{
public
override
string
ToString()
{
return
"
ChildB
"
;
}
}
class
Program
{
static
void
Main(
string
[] args)
{
using
(IUnityContainer container
=
new
UnityContainer())
{
Parent objParent
=
container.Resolve
<
Parent
>
();
Console.WriteLine(objParent.ToString());
Console.ReadKey();
}
}
}

2011041617043372.jpg

  

  接下通过一个简单的配置文件实例例子进一步说明,Unity是如何实现类与类之间的解耦的。

  首先我们先定义一个Foo类,它依赖于一个接口ILogger,它有两个实现分别是LoggerA和LoggerB,然后我们的Foo类要调用LoggerA。在一般情况下我们可以实例化一个LoggerA的实例,然后传递给Foo就OK了,这就是hard code给我们带来了一个紧的耦合,如果要我们修改成调用LoggerB,那么我们可以再实例化一个LoggerB对象,眼前看来是可以这样实现,但如果我们工程很大,这种做法是十分危险,当我们使用配置文件可以简单实现,来讲讲简单实现。

2011041617061238.jpg

 
static
void
Main(
string
[] args)
{
using
(IUnityContainer container
=
new
UnityContainer())
{
///
/Parent objParent = container.Resolve
<Parent>
();
///
/Console.WriteLine(objParent.ToString());
///
/Console.ReadKey();
//
获取指定名称的配置节
UnityConfigurationSection section
=
(UnityConfigurationSection)ConfigurationManager.GetSection(
"
unity
"
);
//
获取container名称为CfgClass下的配置
section.Containers[
"
CfgClass
"
].Configure(container);
Foo myFoo
=
container.Resolve
<
Foo
>
();
Console.WriteLine(myFoo.ToString());
Console.ReadKey();
}
}

App.config中的配置如下:

 
<
configuration
>
<
configSections
>
<!--
每次都必须定义的开头
-->
<
section
name
="unity"
type
="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration"
/>
</
configSections
>
<!--
使用unity的xsd
-->
<!--
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
-->
<
unity
>
<!--
声明一种是用类型
-->
<
typeAliases
>
<
typeAlias
alias
="ILogger"
type
="MSEnterpriseUnitity.ILogger, MSEnterpriseUnitity"
/>
</
typeAliases
>
<
containers
>
<
container
name
="CfgClass"
>
<!--
设定该类型的映射关系
-->
<
types
>
<
type
type
="ILogger"
mapTo
="MSEnterpriseUnitity.LoggerA, MSEnterpriseUnitity"
/>
</
types
>
</
container
>
</
containers
>
</
unity
>
</
configuration
>

二、方法注入

  当一个类的方法依赖于其他类的时候(例如构造函数参数依赖与其他类),在一般情况下通过实例化该被依赖类对象,然后将参数传递给我们依赖类的方法,如果使用方法注入可以避免实例化被依赖类对象,这里就仅仅需要在依赖方法中设置一个属性InjectionMethod就OK了。

 

2.1方法依赖于具体类

  首先我们定义两个类MyTargetOjbect和OtherObject,然后定义在MyTargetOjbect中定义一个方法Initialize(OtherObject dep),该方法的参数依赖于OtherObject类。

 
///
<summary>
///
依赖类包含一个Description和OutPut方法。
///
</summary>
public
class
OtherObject
{
private
string
_description;
public
string
Description
{
get
{
return
_description; }
set
{ _description
=
value; }
}
public
void
OutPut()
{
Console.WriteLine(
this
.Description);
}
}
 
///
<summary>
///
目标类的方法Initialize参数依赖于OtherObject类。
///
</summary>
public
class
MyTargetOjbect
{
public
OtherObject dependentObject;
[InjectionMethod]
public
void
Initialize(OtherObject dep)
{
this
.dependentObject
=
dep;
}
}
 
using
(IUnityContainer container
=
new
UnityContainer())
{
MyTargetOjbect myTargetObject
=
container.Resolve
<
MyTargetOjbect
>
();
myTargetObject.dependentObject.Description
=
"
Injection successful.
"
;
myTargetObject.dependentObject.OutPut();
}

2011041617111471.jpg

2.2 方法依赖于接口或者基类

  定义一个抽象类MyBaseClass,然后MyInheritBase继承该抽象类,定义一个接口IMyInterface然后ImplementInterface实现该接口。

 
///
<summary>
///
接口包含一个属性和一个方法
///
</summary>
public
interface
IMyInterface
{
string
Description
{
get
;
set
;
}
void
OutPut();
}
 
///
<summary>
///
实现IMyInterface的属性和方法
///
</summary>
public
class
ImplementInterface : IMyInterface
{
private
string
_description;
#region
IMyInterface 成员
public
string
Description
{
get
{
return
_description;
}
set
{
_description
=
value;
}
}
public
void
OutPut()
{
Console.WriteLine(
this
.Description);
}
#endregion
}
 
///
<summary>
///
一个抽象类包含一个属性和一个方法
///
</summary>
public
abstract
class
MyBaseClass
{
private
string
_description;
public
virtual
string
Description
{
get
{
return
_description; }
set
{ _description
=
value; }
}
public
abstract
void
OutPut();
}
 
///
<summary>
///
实现抽象类的抽象方法
///
</summary>
public
class
MyInheritBase : MyBaseClass
{
public
override
void
OutPut()
{
Console.WriteLine(
this
.Description);
}
}
 
///
<summary>
///
目标类的方法Initialize参数依赖于OtherObject类。
///
</summary>
public
class
MyTargetOjbect
{
public
IMyInterface myInterface;
public
MyBaseClass myBase;
[InjectionMethod]
public
void
Initialize(IMyInterface myInterface, MyBaseClass myBase)
{
this
.myInterface
=
myInterface;
this
.myBase
=
myBase;
}
}
 
///
/设置抽象类和接口的映射关系
container.RegisterType
<
MyBaseClass, MyInheritBase
>
();
container.RegisterType
<
IMyInterface, ImplementInterface
>
();
MyTargetOjbect myTargetObject
=
container.Resolve
<
MyTargetOjbect
>
();
myTargetObject.myInterface.Description
=
"
Injection Successful.
"
;
myTargetObject.myInterface.OutPut();
myTargetObject.myBase.Description
=
"
Injection Successful.
"
;
myTargetObject.myBase.OutPut();

2011041617154273.jpg

三、属性注入

  当一个类的属性依赖于其他类,一般情况初始化该属性需要实例化该类型对象,然而我们可以使用Dependency属性,指定属性注入无限手动实例化类型对象。

3.1 具体类型属性

 
public
class
MyObject
{
private
SomeOtherObject _dependentObject;
[Dependency]
public
SomeOtherObject DependentObject
{
get
{
return
_dependentObject; }
set
{ _dependentObject
=
value; }
}
}
IUnityContainer uContainer
=
new
UnityContainer();
MyObject myInstance
=
uContainer.Resolve
<
MyObject
>
();
//
now access the property containing the dependency
SomeOtherObject depObj
=
myInstance.DependentObject;

3.2抽象类或接口属性

 
public
class
MyObject
{
private
IMyInterface _interfaceObj;
private
MyBaseClass _baseObj;
[Dependency]
public
IMyInterface InterfaceObject
{
get
{
return
_interfaceObj; }
set
{ _interfaceObj
=
value; }
}
[Dependency]
public
MyBaseClass BaseObject
{
get
{
return
_baseObj; }
set
{ _baseObj
=
value; }
}
}
IUnityContainer uContainer
=
new
UnityContainer()
.RegisterType
<
IMyInterface, FirstObject
>
()
.RegisterType
<
MyBaseClass, SecondObject
>
();
MyObject myInstance
=
uContainer.Resolve
<
MyObject
>
();
//
now access the properties containing the dependencies
IMyInterface depObjA
=
myInstance.InterfaceObject;
MyBaseClass depObjB
=
myInstance.BaseObject;

3.3 给属性注入命名

给属性命名只需在Dependency(“name”)定义一个名字就OK了。

 
public
class
MyTargetOjbect
{
public
IMyInterface myInterface;
public
MyBaseClass myBase;
private
IMyInterface _MyProperty1, _MyProperty2;
//
命名属性注入
[Dependency(
"
Property2
"
)]
public
IMyInterface MyProperty2
{
get
{
return
_MyProperty2; }
set
{ _MyProperty2
=
value; }
}
//
命名属性注入
[Dependency(
"
Property1
"
)]
public
IMyInterface MyProperty1
{
get
{
return
_MyProperty1; }
set
{ _MyProperty1
=
value; }
}
}
 
//
调用Property1属性注入
container.RegisterType
<
IMyInterface, ImplementInterface
>
(
"
Property1
"
);
//
调用Property2属性注入
container.RegisterType
<
IMyInterface, ImplementInterface2
>
(
"
Property2
"
);
MyTargetOjbect myTargetObject
=
container.Resolve
<
MyTargetOjbect
>
();
IMyInterface myProperty1
=
myTargetObject.MyProperty1;
IMyInterface myProperty2
=
myTargetObject.MyProperty2;

3.4 构造函数参数的属性注入

  构造函数参数依赖于其他类时候,我们可以考虑使用构造函数注入或者属性注入

 
public
class
Foo
{
private
ILogger _iLogger;
public
Foo([Dependency] ILogger iLogger)
{
this
._iLogger
=
iLogger;
}
public
override
string
ToString()
{
return
string
.Format(
"
Foo depends on {0}.
"
,
this
._iLogger.ToString());
}
}

转载于:https://www.cnblogs.com/rush/archive/2011/04/16/Unity.html

你可能感兴趣的文章
【转】Simulink模型架构指导
查看>>
MYSQL数据库的导出的几种方法
查看>>
SQL Server-5种常见的约束
查看>>
硬件之美
查看>>
[转载]java开发中的23种设计模式
查看>>
表格的拖拽功能
查看>>
函数的形参和实参
查看>>
文字过长 用 ... 表示 CSS实现单行、多行文本溢出显示省略号
查看>>
1Caesar加密
查看>>
【TP SRM 703 div2 500】 GCDGraph
查看>>
MapReduce 重要组件——Recordreader组件 [转]
查看>>
webdriver api
查看>>
apache 实现图标缓存客户端
查看>>
揭秘:黑客必备的Kali Linux是什么,有哪些弊端?
查看>>
linux系统的远程控制方法——学神IT教育
查看>>
springboot+mybatis报错Invalid bound statement (not found)
查看>>
Linux环境下SolrCloud集群环境搭建关键步骤
查看>>
P3565 [POI2014]HOT-Hotels
查看>>
MongoDB的简单使用
查看>>
hdfs 命令使用
查看>>