在使用Prism框架时,我们发现,Prism要求viewmodel对象在UnityContainer中注册时需要以object作为映射,并且由于Navigation的需要,viewmodel对象必须以命名的形式注册。
如下是符合Prism要求的注册方式:
unityContainer.RegisterType<object,viewmodelA>("viewmodelA");
有的场合,我们需要viewmodel作为单例存在,这是我们会在注册时加上生命周期管理:
unityContainer.RegisterType<object,viewmodelA>("viewmodelA",new ContainerControlledLifetimeManager());
这样能够保证viewmodelA在容器管理中不会多次构造,但事实真的如此吗?
假设有一个viewmodelB,其依赖于viewmodelA,所以我们在viewmodelB的构造函数中将viewmodelA注入:
public viewmodelB(viewmodelA viewmodelA)
按照我们的设想,这里的viewmodelA应该是以单例的形式存在,于是我们通过如下程序来验证:
IUnityContainer unityContainer = new UnityContainer(); unityContainer.RegisterType<object,new ContainerControlledLifetimeManager()); unityContainer.RegisterType<object,viewmodelB>("viewmodelB",new ContainerControlledLifetimeManager()); Console.Out.WriteLine(1); unityContainer.Resolve(typeof (object),"viewmodelA"); Console.Out.WriteLine(2); unityContainer.Resolve(typeof (object),"viewmodelA"); Console.Out.WriteLine(3); unityContainer.Resolve(typeof (object),"viewmodelB"); Console.Out.WriteLine(4); unityContainer.Resolve(typeof (object),"viewmodelB");
我们让A、B在构造函数中分别输出一句话,表示自己被构造了,运行的结果如下:
1 viewmodelA Construct Id:0 2 3 viewmodelA Construct Id:1 viewmodelB Construct Id:0 4
第一次Resolve,VMA构造了,第二次Resolve,Unity直接取出了第一次构造的VMA,第三次Resolve时,Unity再次构造了VMA,并注入到VMB中,第四次Resolve取出VMB,这显然与我们的初衷不符。
为何Unity在注入时不去取之前已经构造的VMA呢?通过阅读Unity的源代码和一些实验我们终于了解到,Unity在构造函数注入时,会去找寻匿名的映射,而我们的viewmodelA是命名映射,所以并不会被Unity识别。
还是刚才那个程序,如果我们在RegisterType和Resolve时都不命名:
unityContainer.RegisterType<object,viewmodelA>(new ContainerControlledLifetimeManager()); unityContainer.RegisterType<object,viewmodelB>(new ContainerControlledLifetimeManager()); Console.Out.WriteLine(1); unityContainer.Resolve<viewmodelA>(); Console.Out.WriteLine(2); unityContainer.Resolve<viewmodelA>(); Console.Out.WriteLine(3); unityContainer.Resolve<viewmodelB>(); Console.Out.WriteLine(4); unityContainer.Resolve<viewmodelB>();
那么结果将符合我们的预期:
1 viewmodelA Construct Id:0 2 3 viewmodelB Construct Id:0 4
但是由于Prism导航的缘故,我们不得不给viewmodel映射命名,所以我们的做法是: 不在构造函数中注入任何命名映射对象,这类对象我们通过注入IUnityContainer来Resolve
这里不排除有其他更好的办法,我也是刚刚接触这个东西,如果有更好的办法请分享。
原文链接:https://www.f2er.com/javaschema/286859.html