关于DI容器UnityContainer的Dispose方法释放资源的一点理解
当调用IUnityContainer.Dispose()方法的时候,它会释放所有子容器(也就是采用CreateChildContainer创建出来的容器)和注册为ContainerControlledLifetimeManager的单例对象。下面这个例子能说明问题:IUnit
当调用IUnityContainer.Dispose()方法的时候,它会释放所有子容器(也就是采用CreateChildContainer创建出来的容器)和注册为ContainerControlledLifetimeManager的单例对象。下面这个例子能说明问题:
IUnityContainer moduleContainer=new UnityContainer ();
IUnityContainer viewContainer=moduleContainer.CreateChildContainer();
moduleContainer.RegisterInstance<IUnityContainer>("SaleBus", viewContainer);
int i =viewContainer.GetHashCode();
moduleContainer.Dispose();
IUnityContainer test=moduleContainer.Resolve<IUnityContainer>("SaleBus");//此时会报错,因为父容器已经释放,所有子容器也将被释放。
若这些单例对象继承自IDisposable接口,则会调用这些对象的Dispose方法回收对象。如果RegisterType没有声明为ContainerControlledLifetimeManager(即每次Resolve都重新创建一个对象实例),则即使该对象实现了IDisposable接口,在调用IUnityContainer.Dispose()方法的时候也不会自动调用该对象的Dispose方法。下面这个例子能说明问题:
IUnityContainer moduleContainer=new UnityContainer ();
moduleContainer.RegisterType<ISaleBusCorpView, SaleBusCorpView>(new ContainerControlledLifetimeManager());//SaleBusCorpView是一个类
ISaleBusCorpView view = moduleContainer.Resolve<ISaleBusCorpView>();
ISaleBusCorpView view3 = moduleContainer.Resolve<ISaleBusCorpView>();
int v = view.GetHashCode();
int v3 = view3.GetHashCode();//v和v3的值是相等的,因为SaleBusCorpView注册为ContainerControlledLifetimeManager
moduleContainer.Dispose();//这里会释放掉上面创建的单例对象,如果SaleBusCorpView实现了IDisposable,则会自动调用SaleBusCorpView的Dispose方法执行一些其他的操作。
ISaleBusCorpView view2 = moduleContainer.Resolve<ISaleBusCorpView>();
ISaleBusCorpView view4 = moduleContainer.Resolve<ISaleBusCorpView>();
int v2 = view2.GetHashCode();
int v4 = view4.GetHashCode();//v2和v4的值是相等的,因为SaleBusCorpView注册为ContainerControlledLifetimeManager,但是v2,v4和v,v3的值确实不同的。这说明单例对象已经释放掉了,后面是重新创建的单例对象。
但在这里我有一个疑问,那就是调用该容器的Dispose方法,该容器本身的实例还是存在的,这一点我们可以通过下面代码来测试。
IUnityContainer moduleContainer=new UnityContainer (); IUnityContainer viewContainer=moduleContainer.CreateChildContainer(); moduleContainer.RegisterInstance<IUnityContainer>("SaleBus", viewContainer); int i =viewContainer.GetHashCode(); moduleContainer.Dispose(); IUnityContainer test=moduleContainer.Resolve<IUnityContainer>("SaleBus");//此时会报错,因为父容器已经释放,所有子容器也将被释放。
int j=test.GetHashCode();if(i==j){MessBox.Show("相同的实例");}
这说明viewContainer仍然存在,可能有人会解释到viewContainer是注册在moduleContainer中的单例对象,生存周期是和moduleContainer的生存周期一致的,我也想是这个理由,但是当我Dispose掉viewContainer后,再用viewContainer.CreateChildContainer()来创建子容器,竟然会报错,报viewContainer没有实例化。这点实在是想不通啊,为什么呢?为什么容器存在却不能创建子容器了呢。。。请各位大大如果知道的帮偶解释一下。。。纠结了很久。还一个问题是Prism模块化开发怎么卸载模块,因为我看ModuleLoader 的源码是模块初始化后会向那个initializedModules的list中插入一条记录表明模块已经初始化过了,这个属性是私有的,不公开的,但是我现在的需求是这样的,我是把每个模块生成为TabItem ,我自定义了TabItem的模板,实现了关闭按钮。但是关闭TabItem后再重新点击相同的菜单菜单的时候却生成不了TabItem了,我调试是发现initializedModules已经标注了这个模块已经初始化,不能再进行初始化了(我的Regions是在模块初始化时替换的),我现在是吧源码的ModuleLoader改掉了,加了一个UnloadModule 方法,用来向initializedModules移除一条记录:
public void UnLoadModule(ModuleInfo moduleInfo) { this.initializedModules.Remove(moduleInfo.ModuleType); }
然后在TabItem关闭的时候调用这个UnLoadModule移除模块初始化标记。这样就可以重新生成TabItem了。不知道这样做有什么坏处,为什么P&P小组没有提供卸载模块的方法。我看RI里面生成页签模块的时候那个页签是不可关闭的,所以不卸载模块不会有影响,当点击sell&buy时自动切换到那个页签了。
或者谁有使用Prism进行模块化开发更好的主程序框架设计,希望不吝赐教啊。。。。
更多推荐
所有评论(0)