您的位置:首页 > 移动开发 > Unity3D

(转)[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)

2010-11-29 17:49 746 查看
原文地址:/article/4792193.html

今天继续介绍Unity,在上一篇的文章中,我介绍了使用UnityContainer来注册对象之间的关系、注册已存在的对象之间的关系,同时着重介绍了Unity内置的各种生命周期管理器的使用方法,今天则主要介绍Unity的Register和Resolve的一些高级应用。

本篇文章将主要介绍:

1、注册类型同时初始化构造函数参数并重载调用。

2、注册类型同时初始化属性参数并重载调用。

3、延迟获取对象。

4、检索检索容器中注册信息。



[b]一、注册类型同时初始化构造函数参数并重载调用[/b]

我们在使用Unity中注册对象之间的关系时,可能对象有相应的构造函数,构造函数中需要传递相应的参数,Unity就支持这样的注册,其主要靠InjectionConstructor这个类来完成,我们首先来看下具体的类构造函数:

viewsourceprint?
1
public
YourClass(
string
test,MyClassmy)
2
{
3
Console.WriteLine(test);
4
Console.WriteLine(my.ToString());
5
}
这个构造函数有2个参数,一个字符串和一个MyClass类对象,相应的可以使用如下代码进行注册:

viewsourceprint?
1
//由于所注册的对象的有带有参数的构造函数,所以注册类型时需要提供相应的参数
2
//这边采用InjectionConstructor这个类来实现
3
container.RegisterType<IClass,YourClass>(
4
new
InjectionConstructor(
"a"
,
new
MyClass()));
5
Console.WriteLine(
"-----------默认调用输出-------------"
);
6
container.Resolve<IClass>();
这样既可完成对象注册的同时对构造函数参数进行注入,此时还有另外一个需求,就是虽然在注册的时候已经对构造函数参数进行了初始化,但是在调用的时候我们想更换原先注册的值,这时应该怎么办?

在Unity中,已经帮我们解决了这个问题,我们可以通过ParameterOverride和ParameterOverrides来实现,其中ParameterOverride是针对一个参数,而ParameterOverrides是针对参数列表,有关注册参数初始化及参数重载的全部代码如下:

viewsourceprint?
01
public
static
void
ResolveParameter()
02
{
03
//由于所注册的对象的有带有参数的构造函数,所以注册类型时需要提供相应的参数
04
//这边采用InjectionConstructor这个类来实现
05
container.RegisterType<IClass,YourClass>(
06
new
InjectionConstructor(
"a"
,
new
MyClass()));
07
Console.WriteLine(
"-----------默认调用输出-------------"
);
08
container.Resolve<IClass>();
09
10
Console.WriteLine(
"-----------重载后调用输出-------------"
);
11
//以下2种Resolve方法效果是一样的
12
//对于参数过多的时候可以采用第2种方法,如果参数仅仅只有1个可以用第1种
13
//container.Resolve<IClass>(newParameterOverride("test","test"),
14
//newParameterOverride("my","newMyClass").OnType<MyClass>());
15
container.Resolve<IClass>(
new
ParameterOverrides()
16
{
17
{
"test"
,
"test"
},
18
{
"my"
,
new
MyClass()}
19
}.OnType<YourClass>());
20
}
其中需要注意的是:

1、在使用ParameterOverride方法来重载参数时,如果注册的参数是一个具体的对象就需要使用OnType这个扩展方法来指定对应的类型,否则会报错。

2、在使用ParameterOverrides进行重载参数时,可以使用如上面代码的方式进行指定,但是同样需要使用OnType来指定,不过这个的OnType指定的类型是注册的对象类型。

效果图如下:





可以看出,其中第一个字符串参数在重载后调用时已经发生了更改。

[b]二、注册类型同时初始化属性并重载调用[/b]

这个初始化属性和上面的初始化参数很类似,只不过不同的是,属性的注册初始化是使用InjectionProperty,而重载属性是使用的PropertyOverride和PropertyOverrides,其使用方法也是相同的,这边就不多介绍了,代码如下:

viewsourceprint?
01
public
static
void
ResolveProperty()
02
{
03
//注册对象关系时初始化对象的属性
04
container.RegisterType<IClass,MyClass>(
05
new
InjectionProperty(
"Name"
,
"A班"
),
06
new
InjectionProperty(
"Description"
,
"A班的描述"
));
07
Console.WriteLine(
"-----------默认调用输出-------------"
);
08
Console.WriteLine(container.Resolve<IClass>().Name);
09
Console.WriteLine(container.Resolve<IClass>().Description);
10
Console.WriteLine(
"-----------重载后调用输出-------------"
);
11
//以下2种写法效果是一样的,同上面的构造函数参数重载
12
//varmyClass=container.Resolve<IClass>(newPropertyOverride("Name","重载后的A班"),
13
//newPropertyOverride("Description","重载后的A班的描述"));
14
varmyClass=container.Resolve<IClass>(
new
PropertyOverrides()
15
{
16
{
"Name"
,
"重载后的A班"
},
17
{
"Description"
,
"重载后的A班的描述"
}
18
}.OnType<MyClass>());
19
20
Console.WriteLine(myClass.Name);
21
Console.WriteLine(myClass.Description);
22
}
效果图如下:





可以看到2个属性都已经被重载了。

Unity还为我们提供了一个DependencyOverride重载,其使用方法和参数重载、属性重载类似,这边就不演示了,不过需要注意的是DependencyOverride是针对所注册对象类型中所包含的对象类型重载,例如在A类中有构造函数参数是B类,同时也有个属性依赖于B类,当使用了DependencyOverride后,这个A对象原先注册的有关B类的依赖将全部改变。(具体可查看示例代码中的ResolveDependency)

[b]三、延迟获取对象[/b]

Unity还有个很不错的特性就是支持延迟获取,其本质是通过事先建立一个委托,然后再调用这个委托,看下下面的代码:

viewsourceprint?
01
public
static
void
DeferringResolve()
02
{
03
varresolver=container.Resolve<Func<IClass>>();
04
05
//根据业务逻辑做其他事情。
06
07
//注册IClass与MyClass之间的关系
08
container.RegisterType<IClass,MyClass>();
09
//获取MyClass实例
10
varmyClass=resolver();
11
12
varresolver2=container.Resolve<Func<IEnumerable<IClass>>>();
13
14
//根据业务逻辑做其他事情。
15
16
//注册与IClass相关的对象。
17
container.RegisterType<IClass,MyClass>(
"my"
);
18
container.RegisterType<IClass,YourClass>(
"your"
);
19
//获取与IClass关联的所有命名实例
20
varclassList=resolver2();
21
}
这段代码演示了2个延迟获取的方式,都是通过将Func<T>放入Resolve<T>中来实现的,返回的是一委托,这样就可以在实际需要的时候再调用这个委托:

1、第一种是事先通过Resolve<Func<IClass>>();来定义获取与IClass关联的对象的委托,然后再注册IClass与MyClass之间的关系,然后再通过resolver();来获取。

2、第二种是事先通过Resolve<Func<IEnumerable<IClass>>>();来定义获取一个与IClass关联的命名实例列表的委托,然后调用相应的委托就可以一次性获取与IClass关联的所有命名实例。

这2种方式都很好的展示了Unity可以更加灵活的控制对象之间的注册与对象的调用。



[b]四、检索容器中注册信息[/b]

当我们在不断使用Unity容器的过程中,我们有时候想看一下容器中到底注册了多少对象,以及各个对象的一些信息,如:什么对象和什么对象关联、具体的注册名称和使用的生命周期管理器,这些信息都可以在容器的Registrations属性中查看到,在Unity文档中已经有个方法来查看这些信息了,代码如下:

viewsourceprint?
01
public
static
void
DisplayContainerRegistrations(IUnityContainertheContainer)
02
{
03
string
regName,regType,mapTo,lifetime;
04
Console.WriteLine(
"容器中{0}个注册信息:"
,
05
theContainer.Registrations.Count());
06
foreach
(ContainerRegistrationitem
in
theContainer.Registrations)
07
{
08
regType=item.RegisteredType.Name;
09
mapTo=item.MappedToType.Name;
10
regName=item.Name??
"[默认]"
;
11
lifetime=item.LifetimeManagerType.Name;
12
if
(mapTo!=regType)
13
{
14
mapTo=
"->"
+mapTo;
15
}
16
else
17
{
18
mapTo=
string
.Empty;
19
}
20
lifetime=lifetime.Substring(0,lifetime.Length-
"生命周期管理器"
.Length);
21
Console.WriteLine(
"+{0}{1}'{2}'{3}"
,regType,mapTo,regName,lifetime);
22
}
23
}
具体的注册代码如下:

viewsourceprint?
01
public
static
void
RegisterAll()
02
{
03
container.RegisterType<IClass,MyClass>(
"my"
);
04
container.RegisterType<IClass,YourClass>(
"your"
,
05
new
ExternallyControlledLifetimeManager());
06
container.RegisterType<ISubject,Subject1>(
"subject1"
);
07
container.RegisterType<ISubject,Subject2>(
"subject2"
);
08
09
DisplayContainerRegistrations(container);
10
}
效果图如下:





可以看到,我在代码中注册的信息都已经很好的反应出来了。

同时如果想查看某个对象是否已经被注册,可以通过container.IsRegistered<T>来验证,这边就不演示了。

以上就是本文的所有内容了,主要介绍了Unity的Register和Resolve的一些高级应用,英文好的朋友可以直接查看Unity的官方文档。

示例代码下载:点我下载

注意:本文示例代码是基于VS2010+Unity2.0,所以请使用VS2010打开,如果没有安装VS2010,请将相关代码复制到相应的VS中运行既可

[b]微软企业库5.0学习之路系列文章索引:[/b]

第一步、基本入门

第二步、使用VS2010+DataAccess模块建立多数据库项目

第三步、为项目加上异常处理(采用自定义扩展方式记录到数据库中)

第四步、使用缓存提高网站的性能(EntLibCaching)

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——上篇

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——中篇

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇

第六步、使用Validation模块进行服务器端数据验证

第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—上篇

第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇

第八步、使用ConfigurationSetting模块等多种方式分类管理企业库配置信息

第九步、使用PolicyInjection模块进行AOP—PART1——基本使用介绍

第九步、使用PolicyInjection模块进行AOP—PART2——自定义MatchingRule

第九步、使用PolicyInjection模块进行AOP—PART3——内置CallHandler介绍

第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义CallHandler实现用户操作日志记录

第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity?

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(2)

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)

第十步、使用Unity解耦你的系统—PART3——依赖注入

扩展学习:

扩展学习篇、库中的依赖关系注入(重构MicrosoftEnterpriseLibrary)[转]

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐
章节导航