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

本篇文章将主要介绍:

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

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

3、延迟获取对象。

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

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

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

public YourClass(string test, MyClass my)
{
Console.WriteLine(test);
Console.WriteLine(my.ToString());
}

这个构造函数有2个参数,一个字符串和一个MyClass类对象,相应的可以使用如下代码进行注册:

//由于所注册的对象的有带有参数的构造函数,所以注册类型时需要提供相应的参数
//这边采用InjectionConstructor这个类来实现
container.RegisterType<IClass, YourClass>(
new InjectionConstructor("a", new MyClass()));
Console.WriteLine("-----------默认调用输出-------------");
container.Resolve<IClass>();

这样既可完成对象注册的同时对构造函数参数进行注入,此时还有另外一个需求,就是虽然在注册的时候已经对构造函数参数进行了初始化,但是在调用的时候我们想更换原先注册的值,这时应该怎么办?

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

public static void ResolveParameter()
{
//由于所注册的对象的有带有参数的构造函数,所以注册类型时需要提供相应的参数
//这边采用InjectionConstructor这个类来实现
container.RegisterType<IClass, YourClass>(
new InjectionConstructor("a", new MyClass()));
Console.WriteLine("-----------默认调用输出-------------");
container.Resolve<IClass>(); Console.WriteLine("-----------重载后调用输出-------------");
//以下2种Resolve方法效果是一样的
//对于参数过多的时候可以采用第2种方法,如果参数仅仅只有1个可以用第1种
//container.Resolve<IClass>(new ParameterOverride("test", "test"),
// new ParameterOverride("my", "new MyClass").OnType<MyClass>());
container.Resolve<IClass>(new ParameterOverrides()
{
{"test","test"},
{"my",new MyClass()}
}.OnType<YourClass>());

其中需要注意的是:

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

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

效果图如下:

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

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

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

public static void ResolveProperty()
{
//注册对象关系时初始化对象的属性
container.RegisterType<IClass, MyClass>(
new InjectionProperty("Name", "A班"),
new InjectionProperty("Description", "A班的描述"));
Console.WriteLine("-----------默认调用输出-------------");
Console.WriteLine(container.Resolve<IClass>().Name);
Console.WriteLine(container.Resolve<IClass>().Description);
Console.WriteLine("-----------重载后调用输出-------------");
//以下2种写法效果是一样的,同上面的构造函数参数重载
//var myClass = container.Resolve<IClass>(new PropertyOverride("Name", "重载后的A班"),
// new PropertyOverride("Description", "重载后的A班的描述"));
var myClass = container.Resolve<IClass>(new PropertyOverrides()
{
{"Name","重载后的A班"},
{"Description","重载后的A班的描述"}
}.OnType<MyClass>()); Console.WriteLine(myClass.Name);
Console.WriteLine(myClass.Description);
}

效果图如下:

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

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

三、延迟获取对象

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

public static void DeferringResolve()
{
var resolver = container.Resolve<Func<IClass>>(); //根据业务逻辑做其他事情。 //注册IClass与MyClass之间的关系
container.RegisterType<IClass, MyClass>();
//获取MyClass实例
var myClass = resolver(); var resolver2 = container.Resolve<Func<IEnumerable<IClass>>>(); //根据业务逻辑做其他事情。 //注册与IClass相关的对象。
container.RegisterType<IClass, MyClass>("my");
container.RegisterType<IClass, YourClass>("your");
//获取与IClass关联的所有命名实例
var classList = resolver2();
}

这段代码演示了2个延迟获取的方式,都是通过将Func<T>放入Resolve<T>中来实现的,返回的是一委托,这样就可以在实际需要的时候再调用这个委托:

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

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

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

四、检索容器中注册信息

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

public static void DisplayContainerRegistrations(IUnityContainer theContainer)
{
string regName, regType, mapTo, lifetime;
Console.WriteLine("容器中 {0} 个注册信息:",
theContainer.Registrations.Count());
foreach (ContainerRegistration item in theContainer.Registrations)
{
regType = item.RegisteredType.Name;
mapTo = item.MappedToType.Name;
regName = item.Name ?? "[默认]";
lifetime = item.LifetimeManagerType.Name;
if (mapTo != regType)
{
mapTo = " -> " + mapTo;
}
else
{
mapTo = string.Empty;
}
lifetime = lifetime.Substring(, lifetime.Length - "生命周期管理器".Length);
Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo, regName, lifetime);
}
}

具体的注册代码如下:

public static void RegisterAll()
{
container.RegisterType<IClass, MyClass>("my");
container.RegisterType<IClass, YourClass>("your",
new ExternallyControlledLifetimeManager());
container.RegisterType<ISubject, Subject1>("subject1");
container.RegisterType<ISubject, Subject2>("subject2"); DisplayContainerRegistrations(container);
}

效果图如下:

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

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

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

示例代码下载:点我下载

最新文章

  1. kaungbin_DP S (POJ 3666) Making the Grade
  2. Spring注解@Value的用法
  3. C# 获取DataTable数据导出到Excel
  4. Normalize.css
  5. 常用的PC/SC接口函数
  6. css基础之 font的简写规则 以及 自定义 CSS3 @font-face详细用法
  7. 论山寨手机与Android联姻的技术基础 【序】
  8. Unreal Engine 4 C++ 能够创建角色Zoom摄像头(资源)
  9. HTML5分析实战WebSockets基本介绍
  10. elasticsearch 源码本地环境搭建
  11. 关于Java的异常
  12. 任务定义器——SocketProcessor
  13. C#获取网页的HTML码、下载网站图片 get post
  14. 使用Ajax异步上传图片的方法(html,javascript,php)
  15. crawlspider 多分页处理
  16. F. Ivan and Burgers(线性基,离线)
  17. macos安装postman
  18. 2017 清北济南考前刷题Day 6 afternoon
  19. LeetCode: Divide Two Integers 解题报告
  20. JavaScript三大对象详细解说

热门文章

  1. u3d图片转视频
  2. 第2章-Vue.js指令
  3. mysql主从同步碰到的问题
  4. Jenkins使用教程之用户权限管理(包含插件的安装)
  5. NOIP模拟7
  6. 2017.5.27 NOIP模拟赛(hzwer2014-5-16 NOIP模拟赛)
  7. Material Design 之 TabLayout 使用
  8. 01 DIV+CSS 固定页面布局
  9. Tinyos 第三版Make系统
  10. css3旋转、过渡、动画属性