加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

UnityContainer通过构造函数依赖注入的问题

发布时间:2020-12-13 20:05:59 所属栏目:百科 来源:网络整理
导读:在使用Prism框架时,我们发现,Prism要求ViewModel对象在UnityContainer中注册时需要以object作为映射,并且由于Navigation的需要,ViewModel对象必须以命名的形式注册。 如下是符合Prism要求的注册方式: unityContainer.RegisterTypeobject,ViewModelA("Vi

在使用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

这里不排除有其他更好的办法,我也是刚刚接触这个东西,如果有更好的办法请分享。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读