关于DI容器UnityContainer的Dispose方法释放资源的一点理解

当调用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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF Prism框架是一个非常强大的框架,可以帮助我们快速开发出高质量的WPF应用程序,其中Unity容器Prism框架中用于依赖注入的核心组件。下面是Unity容器的注册代码示例: ```csharp // 创建Unity容器 IUnityContainer container = new UnityContainer(); // 注册类型 container.RegisterType<IMyInterface, MyConcreteClass>(); // 注册单例 container.RegisterSingleton<IMySingleton, MySingletonClass>(); // 注册实例 IMyInstance myInstanceObject = new MyInstanceClass(); container.RegisterInstance<IMyInstance>(myInstanceObject); // 注册工厂 container.RegisterFactory<IMyFactory>( c => new MyFactoryClass(c.Resolve<IMyDependency>()) ); // 注册命名空间下的所有类型 container.RegisterTypes( AllClasses.FromLoadedAssemblies().Where(type => type.Namespace == "MyNamespace"), WithMappings.FromMatchingInterface, WithName.Default ); // 注册特定条件下的类型 container.RegisterTypes( AllClasses.FromLoadedAssemblies().Where(type => type.Name.EndsWith("Service")), WithMappings.FromMatchingInterface, WithName.Default, WithLifetime.ContainerControlled ); // 注册自定义实例化方式 container.RegisterType<IMyClass>( new InjectionFactory(c => { string someParameter = "some value"; return new MyClass(someParameter, c.Resolve<IMyDependency>()); }) ); ``` 以上示例代码展示了Unity容器的基本用法,包括注册类型、单例、实例、工厂、命名空间和特定条件下的类型,并且还演示了如何使用自定义实例化方式来创建对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值