如何销毁使用 MEF 创建的对象

发布于 2024-10-10 04:46:38 字数 2077 浏览 0 评论 0原文

您好,我在 WPF 应用程序中使用 MEF 和 caliburn.micro。我想知道如何销毁使用 MEF 创建的实例。

例如简单的 shell:

 [Export(typeof(IShellViewModel))]
    public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IShellViewModel
    {

        protected override void OnInitialize()
        {
            ShowLogOn();
            base.OnInitialize();
        }

        //first screen
        public void ShowLogOn()
        {
            var vm = IoC.Get<ILogOnViewModel>();
            ActivateItem(vm);
        }

        //second screen
        public void ShowMessenger(Account account)
        {
            ActiveItem.Deactivate(true);
            var vm = IoC.Get<IMessengerViewModel>();
            vm.Account = account;
            ActivateItem(vm);
        }

  }

第一个屏幕

[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen,ILogOnViewModel
{
   User user=new User();
}

第二个屏幕:

  [Export(typeof(IMessengerViewModel))]
            public class MessengerViewModel : Screen, IViewModelIdentity,
                IMessengerViewModel, IHandle<Rp>, IHandle<string>
            {..}

WPF 应用程序从与 ILogOnViewModel 界面关联的第一个屏幕启动。然后我停用此屏幕并激活与 IMessengerViewModel 界面关联的第二个屏幕。

我使用 ANTS Mememory Profiler 检查内存使用情况,但 ILogOnViewModel 的实例仍然存在,User 类的实例也存在。

我是 IoC、DI 方面的新手...所有使用 MEF 导出的类都必须在整个 WPF 应用程序生命周期内存在?

其他示例,我使用窗口管理器创建新的 wpf 窗口。

[Export(typeof(IChatViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChatViewModel : Screen, IViewModelIdentity, 
    IChatViewModel, IHandle<Rp>, IHandle<DetailData>
{}

ChatViewModel 是 WPF 窗口。

创建 IChatViewModel 的实例:

private IWindowManager _windowManager;
var chatScreen = IoC.Get<IChatViewModel>();
_windowManager.Show(chatScreen);

然后关闭(单击窗口上的 X(关闭)按钮)WPF 窗口,ChatViewModel 已停用 但这个类的实例仍然存在。

它的存在方式是如何杀死/销毁这个实例?

Hi I use MEF and caliburn.micro in WPF app. I would like know how can I destroy instaces created with MEF.

For example simple shell:

 [Export(typeof(IShellViewModel))]
    public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IShellViewModel
    {

        protected override void OnInitialize()
        {
            ShowLogOn();
            base.OnInitialize();
        }

        //first screen
        public void ShowLogOn()
        {
            var vm = IoC.Get<ILogOnViewModel>();
            ActivateItem(vm);
        }

        //second screen
        public void ShowMessenger(Account account)
        {
            ActiveItem.Deactivate(true);
            var vm = IoC.Get<IMessengerViewModel>();
            vm.Account = account;
            ActivateItem(vm);
        }

  }

First screen

[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen,ILogOnViewModel
{
   User user=new User();
}

Second screen:

  [Export(typeof(IMessengerViewModel))]
            public class MessengerViewModel : Screen, IViewModelIdentity,
                IMessengerViewModel, IHandle<Rp>, IHandle<string>
            {..}

WPF app start with first screen associated with ILogOnViewModel interface. Then I deactivate this screen and activate second screen associated with IMessengerViewModel interface.

I check memory usage with ANTS Mememory profiler but instace of ILogOnViewModel is still alive also instace of class User is alive.

I am newbie in IoC, DI... all class which are exported with MEF must live during the whole WPF application lifetime cycle?

Other example, I create new wpf window with window manager.

[Export(typeof(IChatViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChatViewModel : Screen, IViewModelIdentity, 
    IChatViewModel, IHandle<Rp>, IHandle<DetailData>
{}

ChatViewModel is WPF Window.

Create instance of IChatViewModel:

private IWindowManager _windowManager;
var chatScreen = IoC.Get<IChatViewModel>();
_windowManager.Show(chatScreen);

Then I close (click on X (close) button on window) WPF Window, ChatViewModel is deactivated
but instace of this class is still alive.

It exist way how kill/destroy this instaces?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

唱一曲作罢 2024-10-17 04:46:38

MEF 容器负责管理导出的生命周期,因此无论使用哪个 CreationPolicy(默认为 Shared),最终都会调用容器的 Dispose 方法将处理任何 Export 实例(包装您的实际类实例)。此外,在 Export 实例上调用 Dispose 也会导致实际的类实例也被释放。

要记住的事情是,GC 正在查看对象图并确定是否有 0 个或多个对该特定实例的引用,因为引用是由 MEF CompositionContainer 维护的(包装在 < code>Export)它不会处理该项目。

如果您强制在插件中实现IDisposable,例如

public interface ILogOnViewModel : IDisposable { }

并确保在实现处置模式时,您允许多次调用它:

public void Dispose(bool disposing)
{
    if (disposing && !disposed)
    {
        // Clean up?
    }
}

public void Dispose()
{
    Dispose(true);
    GC.SurpressFinalize(this);
}

然后您可以安全地调用Dispose在您的 ILogOnViewModel 实现实例上,而不会在实际容器处置时造成问题。

The MEF container is responsible for managing the lifetime of your exports, so regardless of which CreationPolicy is used (default is Shared), the final call to the container's Dispose method will dispose of any Export instances (which wrap your actual class instances). Also, calling Dispose on an Export instance will cause the actual class instance to dispose also.

The thing to remember, is the GC is looking at the object graph and determining if there are 0 or more references to that particular instance, because a reference is maintained by the MEF CompositionContainer (wrapped up in an Export) it won't dispose of that item.

If you enforce that IDisposable is implemented in your plugins, e.g.

public interface ILogOnViewModel : IDisposable { }

And ensure that when implementing the dispose pattern, you allow it to be called multiple times:

public void Dispose(bool disposing)
{
    if (disposing && !disposed)
    {
        // Clean up?
    }
}

public void Dispose()
{
    Dispose(true);
    GC.SurpressFinalize(this);
}

You can then safely call Dispose on your instance of your ILogOnViewModel implementation without causing problems when the actual container disposes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文