在分析PRISM项目的时候, 发现里面用到了Unity 这个Component, 主要用于依赖注入的。由于对其不熟悉,索性分析了一下,记载在此,以作备忘。
任何事物的出现,总有它独特的原因,Unity也是如此。
在Unity产生之前,我们是这么做的
在远古的时候,当我们需要在一个类A中引用另一个类B的时候,总是将类B的实例放置到类A的构造函数中,以便在初始化类A的时候,得到类B的实例。
1 public class A 2 { 3 B b; 4 public A() 5 { 6 B = new B(); 7 } 8 }
但是,当项目稍微大一点的时候,维护起来就显得异常吃力,尤其是当有Code Change的时候,如果类B有了一些修改(比如加入了带参构造等等),那么这种修改和测试将是异常难受的。
所以,为了解决最原始的问题,我们开始在类A的外部获取类B的实例,以便能够减轻依赖:
有了问题,才会思考变化,于是接口开始在这方面体现他的威力了:
1 public class A 2 { 3 IMyObject myObj; 4 public A(IMyObject myObj) 5 { 6 this.myObj = myObj; 7 } 8 }
将相似的操作抽出来,放入接口中。现在,你就拥有了许多可以操纵的类对象(继承了IService接口的类)。并且采用接口以后,你可以更加容易的进行开发和测试,并且维护起来也相对简单。比如,如果你想测试接口中的DataExtracting功能,那么你完全可以写一个类继承自这个接口,只实现DataExtracting功能即可,简单,方便。
在Unity产生之后,我们是这么做的
现在,Unity将这种操作更加的简单化,我们可以理解为这样,Unity将继承了接口的类进行了横切,然后提供了还原的方法:
进行依赖注入:
1 UnityContainer container = new UnityContainer(); 2 3 private void button1_Click(object sender, EventArgs e) 4 { 5 container.RegisterType<IMyObject, MyObjectFirstImplementation>(DependencyRegistrationKeys.FirstImplementation); 6 container.RegisterType<IMyObject, MyObjectSecondImplementation>(DependencyRegistrationKeys.SecondImplementation); 7 8 container.RegisterType<IMyObject, MyObjectThirdImplementation>(); 9 container.RegisterType<IMyObject, MyObjectFirstImplementation>(); 10 11 }
还原实体类:
1 public MyObjectFactory(UnityContainer unityContainer) 2 { 3 this.unityContainer = unityContainer; 4 } 5 6 public UnityContainer unityContainer; 7 8 public IMyObject Create(string objKey) 9 { 10 return unityContainer.Resolve<IMyObject>(objKey); 11 } 12
最后给出一个例子作为参考,这个例子主要是讲解Unity如何进行注册对象以及还原的:
实例说明
首先,我们需要有一个IMyObject接口,然后有三个类继承自此对象:
接口:
1 namespace UnityDaemon 2 { 3 public interface IMyObject 4 { 5 string DoSomething(); 6 } 7 }
MyObjectFirstImplementation类:
1 namespace UnityDaemon 2 { 3 public class MyObjectFirstImplementation:IMyObject 4 { 5 public string DoSomething() 6 { 7 return "You call me ? I am the first one, I am from MyObjectFirstImplementation!! "; 8 } 9 } 10 }
MyObjectSecondImplementation类:
1 namespace UnityDaemon 2 { 3 public class MyObjectSecondImplementation:IMyObject 4 { 5 public string DoSomething() 6 { 7 return "You call me ? I am the second one, I am from MyObjectSecondImplementation!! "; 8 } 9 } 10 }
MyObjectThirdImplementation类:
1 namespace UnityDaemon 2 { 3 public class MyObjectThirdImplementation:IMyObject 4 { 5 public string DoSomething() 6 { 7 return "I am the third. Do whatever you want to ~~~"; 8 } 9 } 10 }
当然,这里我们还可以增加更多的类...
然后,我们需要创建一个Factory,用于根据Object名称来还原对象:
1 using Microsoft.Practices.Unity; 2 3 namespace UnityDaemon 4 { 5 public class MyObjectFactory 6 { 7 public MyObjectFactory() { } 8 9 public MyObjectFactory(UnityContainer unityContainer) 10 { 11 this.unityContainer = unityContainer; 12 } 13 14 public UnityContainer unityContainer; 15 16 public IMyObject Create(string objKey) 17 { 18 return unityContainer.Resolve<IMyObject>(objKey); 19 } 20 } 21 }
这样做完之后,我们就可以来使用了,我利用Winform做的界面,Button1用来注册类型,Button2用来还原有名称的对象,Button3用来还原无名称的对象:
1 using System; 2 using System.Windows.Forms; 3 using Microsoft.Practices.Unity; 4 5 namespace UnityDaemon 6 { 7 public partial class MainFrm : Form 8 { 9 UnityContainer container; 10 11 public MainFrm() 12 { 13 InitializeComponent(); 14 container = new UnityContainer(); 15 } 16 17 private void button1_Click(object sender, EventArgs e) 18 { 19 container.RegisterType<IMyObject, MyObjectFirstImplementation>(DependencyRegistrationKeys.FirstImplementation); 20 container.RegisterType<IMyObject, MyObjectSecondImplementation>(DependencyRegistrationKeys.SecondImplementation); 21 22 container.RegisterType<IMyObject, MyObjectThirdImplementation>(); 23 container.RegisterType<IMyObject, MyObjectFirstImplementation>(); 24 25 } 26 27 private void button2_Click(object sender, EventArgs e) 28 { 29 var factory = new MyObjectFactory(container); 30 var myObj = factory.Create(DependencyRegistrationKeys.FirstImplementation); 31 string str = myObj.DoSomething(); 32 MessageBox.Show(str); 33 34 var myObj1 = factory.Create(DependencyRegistrationKeys.SecondImplementation); 35 string str1 = myObj1.DoSomething(); 36 MessageBox.Show(str1); 37 } 38 39 private void button3_Click(object sender, EventArgs e) 40 { 41 var myObj1 = container.Resolve<IMyObject>(); 42 43 MessageBox.Show(myObj1.DoSomething()); 44 } 45 } 46 }
这样,当我们运行起来,先点击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
来源:https://www.cnblogs.com/android-blogs/p/6136783.html