在分析PRISM项目的时候, 发现里面用到了Unity 这个Component, 主要用于依赖注入的。由于对其不熟悉,索性分析了一下,记载在此,以作备忘。

任何事物的出现,总有它独特的原因,Unity也是如此。

在Unity产生之前,我们是这么做的

在远古的时候,当我们需要在一个类A中引用另一个类B的时候,总是将类B的实例放置到类A的构造函数中,以便在初始化类A的时候,得到类B的实例。

    public class A
{
B b;
public A()
{
B = new B();
}
}

但是,当项目稍微大一点的时候,维护起来就显得异常吃力,尤其是当有Code Change的时候,如果类B有了一些修改(比如加入了带参构造等等),那么这种修改和测试将是异常难受的。

所以,为了解决最原始的问题,我们开始在类A的外部获取类B的实例,以便能够减轻依赖:

  public class A
{
B b;
public A(B _b)
{
This.b = _b;
}
}
这样,只需要在外部实例化B,然后传入类A即可。这样做,虽然比原始做法方便了许多,然是在类A内部,依然存在着对类B的依赖。由于类B在系统中是唯一的,所以说当有许多个类似于类B的对象需要进行初始化的时候,这种工作量…谁能够想象呢?

有了问题,才会思考变化,于是接口开始在这方面体现他的威力了:

    public class A
{
IMyObject myObj;
public A(IMyObject myObj)
{
this.myObj = myObj;
}
}

将相似的操作抽出来,放入接口中。现在,你就拥有了许多可以操纵的类对象(继承了IService接口的类)。并且采用接口以后,你可以更加容易的进行开发和测试,并且维护起来也相对简单。比如,如果你想测试接口中的DataExtracting功能,那么你完全可以写一个类继承自这个接口,只实现DataExtracting功能即可,简单,方便。

在Unity产生之后,我们是这么做的

现在,Unity将这种操作更加的简单化,我们可以理解为这样,Unity将继承了接口的类进行了横切,然后提供了还原的方法:

进行依赖注入:

    UnityContainer container = new UnityContainer();

         private void button1_Click(object sender, EventArgs e)
{
container.RegisterType<IMyObject, MyObjectFirstImplementation>(DependencyRegistrationKeys.FirstImplementation);
container.RegisterType<IMyObject, MyObjectSecondImplementation>(DependencyRegistrationKeys.SecondImplementation); container.RegisterType<IMyObject, MyObjectThirdImplementation>();
container.RegisterType<IMyObject, MyObjectFirstImplementation>(); }

还原实体类:

 public MyObjectFactory(UnityContainer unityContainer)
{
this.unityContainer = unityContainer;
} public UnityContainer unityContainer; public IMyObject Create(string objKey)
{
return unityContainer.Resolve<IMyObject>(objKey);
}

最后给出一个例子作为参考,这个例子主要是讲解Unity如何进行注册对象以及还原的:

实例说明

首先,我们需要有一个IMyObject接口,然后有三个类继承自此对象:

接口:

 namespace UnityDaemon
{
public interface IMyObject
{
string DoSomething();
}
}

MyObjectFirstImplementation类:

 namespace UnityDaemon
{
public class MyObjectFirstImplementation:IMyObject
{
public string DoSomething()
{
return "You call me ? I am the first one, I am from MyObjectFirstImplementation!! ";
}
}
}

MyObjectSecondImplementation类:

 namespace UnityDaemon
{
public class MyObjectSecondImplementation:IMyObject
{
public string DoSomething()
{
return "You call me ? I am the second one, I am from MyObjectSecondImplementation!! ";
}
}
}

MyObjectThirdImplementation类:

 namespace UnityDaemon
{
public class MyObjectThirdImplementation:IMyObject
{
public string DoSomething()
{
return "I am the third. Do whatever you want to ~~~";
}
}
}

当然,这里我们还可以增加更多的类...

然后,我们需要创建一个Factory,用于根据Object名称来还原对象:

 using Microsoft.Practices.Unity;

 namespace UnityDaemon
{
public class MyObjectFactory
{
public MyObjectFactory() { } public MyObjectFactory(UnityContainer unityContainer)
{
this.unityContainer = unityContainer;
} public UnityContainer unityContainer; public IMyObject Create(string objKey)
{
return unityContainer.Resolve<IMyObject>(objKey);
}
}
}

这样做完之后,我们就可以来使用了,我利用Winform做的界面,Button1用来注册类型,Button2用来还原有名称的对象,Button3用来还原无名称的对象:

 using System;
using System.Windows.Forms;
using Microsoft.Practices.Unity; namespace UnityDaemon
{
public partial class MainFrm : Form
{
UnityContainer container; public MainFrm()
{
InitializeComponent();
container = new UnityContainer();
} private void button1_Click(object sender, EventArgs e)
{
container.RegisterType<IMyObject, MyObjectFirstImplementation>(DependencyRegistrationKeys.FirstImplementation);
container.RegisterType<IMyObject, MyObjectSecondImplementation>(DependencyRegistrationKeys.SecondImplementation); container.RegisterType<IMyObject, MyObjectThirdImplementation>();
container.RegisterType<IMyObject, MyObjectFirstImplementation>(); } private void button2_Click(object sender, EventArgs e)
{
var factory = new MyObjectFactory(container);
var myObj = factory.Create(DependencyRegistrationKeys.FirstImplementation);
string str = myObj.DoSomething();
MessageBox.Show(str); var myObj1 = factory.Create(DependencyRegistrationKeys.SecondImplementation);
string str1 = myObj1.DoSomething();
MessageBox.Show(str1);
} private void button3_Click(object sender, EventArgs e)
{
var myObj1 = container.Resolve<IMyObject>(); MessageBox.Show(myObj1.DoSomething());
}
}
}

这样,当我们运行起来,先点击Button1的时候,三个类都被注册进了容器中。当点击Button2的时候,显示出来的结果和预想一样。当点击Button3的时候,仅仅显示了

You call me ? I am the first one,  I am from MyObjectFirstImplementation!!

原因是什么呢? 原因就在于当注册的时候,没有提供名称的话,那么解析的时候,则以最后一次注册的为准。所以这也是MyObjectThirdImplementation类中的函数没有被执行的原因。

源码下载

点击这里下载

参考连接

http://stackoverflow.com/questions/4612054/wpf-prism-what-is-a-unity-container

http://blogsprajeesh.blogspot.hk/search/label/PRISM

Unity浅析的更多相关文章

  1. 深入理解IOC模式及Unity框架

    研究了下,有几篇博客确实已经说得很清楚了 1.IoC模式:http://www.cnblogs.com/qqlin/archive/2012/10/09/2707075.html  这篇博客是通过一个 ...

  2. Unity系列文章

    1.IoC模式:http://www.cnblogs.com/qqlin/archive/2012/10/09/2707075.html  这篇博客是通过一个播放器的例子来说明什么是依赖,依赖倒置,控 ...

  3. IOC模式及Unity框架文章收藏

    1.IoC模式:http://www.cnblogs.com/qqlin/archive/2012/10/09/2707075.html 通过Unity实现IOC容器. 2.深入理解DIP.IoC.D ...

  4. 浅析Unity中的Enlighten与混合光照

    0x00 前言 在Unity的5.6版本之前的5.x中,主要使用了Geomerics公司的Enlighten[1]来提供实时全局照明以及烘焙全局照明,在5.6之后Unity引入了新的Lightmapp ...

  5. unity协程coroutine浅析

    转载请标明出处:http://www.cnblogs.com/zblade/ 一.序言 在unity的游戏开发中,对于异步操作,有一个避免不了的操作: 协程,以前一直理解的懵懵懂懂,最近认真充电了一下 ...

  6. Unity/C#基础复习(5) 之 浅析观察者、中介者模式在游戏中的应用与delegate原理

    参考资料 [1] <Unity 3D脚本编程 使用C#语言开发跨平台游戏>陈嘉栋著 [2] @张子阳[C#中的委托和事件 - Part.1] http://www.tracefact.ne ...

  7. Esfog_UnityShader教程_UnityShader语法实例浅析

    距离上次首篇前言已经有一段时间了,一直比较忙,今天是周末不可以再拖了,经过我一段时间的考虑,我决定这一系列的教程会避免过于深入细节,一来可以避免一些同学被误导,二来会避免文章过于冗长难读, 三来可以让 ...

  8. Android源码浅析(二)——Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境

    Android源码浅析(二)--Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境 接着上篇,上片主要是介绍了一些安装工具的小知识点Andr ...

  9. Unity ECS 视频笔记

    视频摘要 本文视频资料:使用Entity Component System开发<快乐的Minecraft>游戏 使用Unity2018及以上版本才有ECS功能. 本文是看视频的一些摘要. ...

随机推荐

  1. 通过FEDERATED存储引擎跨实例访问数据

    通过FEDERATED存储引擎同步两实例间的表数据需求情景:实例1中A库中的三个视图是实例2中的B库所依赖的,B需要A库中三个视图的实时数据.方案:通过FEDERATED来完成跨势力的查询FEDERA ...

  2. i++与++i

    #include <stdio.h> int main() { int a,b,c,d; a = 10; b = a++;//相当于两个句子:b = a,a += 1;先使用a的值再加1 ...

  3. HP T505恢复出厂系统

    1.制作usb启动U盘. ------ 从HP网站上下载,或者找供应商提供 2.按F11,从U盘启动进去,会自动执行安装,等待完成即可以.

  4. Linux覆盖率一点研究:获取覆盖率数据

     首先,当然哥不介意你鄙视我在网上找的资料研究! 白盒覆盖率是啥东东这个问题大家自己查百度啦!我也不太懂,就知道它不是个东西,就这样开始吧(MT一般是先摸四蹄呢还是先黑金币呢?这是个问题)! 首先:l ...

  5. SDK截图程序(一)

    程序将系统窗口左上角100*100的图像复制到粘贴板上.程序的关键位置上加上了注释,相关知识<windows程序设计>第14章内容 #include <windows.h> # ...

  6. Launching the Debugger Automatically

    You can set up your application to start Visual Studio when you launch the application from Windows. ...

  7. REDIS 主从复制

      REDIS目前给出了一个异步的主从复制版本系统.在redis里 提供了几种方式来完成这个工作. 主从复制主要对应在redis/replication.c这个文件里.源码框架里 分为3部分: Mas ...

  8. 服务器使用recast navigation

    在3D MMO或者其他类型的游戏中,通常需要进行寻路处理,地图针对寻路有多种方案,比如划分格子,凸多边形等,本篇介绍一种比较常用的navigation mesh的方式来进行寻路.不过整套navmesh ...

  9. bootstrapCDN和本地化

    因为公司网络环境较差和自己是菜鸟的原因,很简单的事情折腾了不少时间.测试开发的网页时候 更新速度总是很慢,这跟使用bootstrapCDN有关系,因为每次更新,它都要重新访问cdn.bootstrap ...

  10. iOS 9正式版开始推送 升级机型非常广泛

    北京时间今日零时,苹果正式推送了iOS9,对于iPhone和iPad来说这一版系统升级都有很多重要改进,而升级的机型也非常宽泛,甚至连2011年的iPad 2与iPhone 4s都获得了支持,所以广大 ...