c# - MEF:GetExportedValue 和 SatisfyImports 之间的区别

标签 c# .net .net-4.0 memory-leaks mef

我们在 MVVM 应用程序中使用 MEF(.NET 4,目前不能使用 4.5)。 一切都很好,直到我们需要动态创建模型,例如表格的可编辑行。 我不想遇到内存泄漏,我找到了这篇文章 http://pglazkov.blogspot.ch/2011/04/mvvm-with-mef-viewmodelfactory.html我发现了一个我想了解的意外行为。 这是添加到 Shell.Items 可观察集合的项目:

[PartCreationPolicy(CreationPolicy.NonShared)]
[Export]
public class Item : INotifyPropertyChanged, IDisposable
{
    [Import]
    private Lazy<Shell> shell;

    /// <summary>
    /// Initializes a new instance of the <see cref="Item"/> class.
    /// </summary>
    public Item()
    {
        this.Time = DateTime.Now;
    }

    ~Item()
    {
        this.Dispose(false);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public Shell Shell
    {
        get
        {
            return this.shell.Value;
        }
    }

    public DateTime Time { get; private set; }

    public void Initialize()
    {
        this.Shell.ItemsCount++;
    }

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

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            this.Shell.ItemsCount--;
        }
    }

    [..]
}

这是工厂:

[PartCreationPolicy(CreationPolicy.Shared)]
[Export]
public class ChildContainerItemFactory : ItemFactory
{
    public override Item Create()
    {
        var container = ServiceLocator.Current.GetInstance<CompositionContainer>();
        using (var childContainer = CreateTemporaryDisposableContainer(container))
        {
            var item = childContainer.GetExportedValue<Item>();
            item.Initialize();
            return item;
        }
    }

    [..]
}

如果我使用此代码,Item 将与子容器一起处理。 如果我将其更改为:

public override Item Create()
    {
        var container = ServiceLocator.Current.GetInstance<CompositionContainer>();
        using (var childContainer = CreateTemporaryDisposableContainer(container))
        {
            var item = new Item();
            childContainer.SatisfyImportsOnce(item);
            item.Initialize();
            return item;
        }
    }

该项目不再与容器一起处理。 我想了解使用 GetExportedValue 方法是否危险(我在应用程序的其他部分使用该方法),对于生命周期较短的 View 模型,这是避免内存泄漏的最佳实践。

感谢任何帮助

最佳答案

据我所知(通过试验和查看 MEF 的 source code ):

  1. 处置容器时,也会处置所有导出的一次性目录部件。导出的目录部件是用 ExportAttribute 修饰或使用 RegistrationBuilder 指定为导出的部件(MEF2)。这些部分由容器创建,它们的生命周期取决于容器本身的生命周期。
  2. 另一方面,使用 CompositionContainer.SatisfyImportsOnce 手动创建和组合的对象或 CompositionContainer.ComposeParts不会被处置。它们的生命周期不依赖于容器的生命周期。

现在GetExportedValue 和SatisfyImports 的区别就不一样了。 GetExportedValue 返回在容器中注册的所有导出部件。这包括由容器创建的部件(1. 中提到的导出目录部件)以及使用 CompositionContainer.ComposeParts 注册的部件。 SatisfyImports 将注入(inject)任何可用的导入,但不会将该对象注册为导出,即使它的类被标记为导出类型(参见 1.)。此外,SatisfyImports 将禁用重组,但这是题外话。

MEF 关于 CodePlex 的文档提供了有关 Parts Lifetime 的宝贵信息.

关于c# - MEF:GetExportedValue 和 SatisfyImports 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18314865/

相关文章:

c# - Google Sheets - 如何通过行索引获取多行数据

c# - 在 Silverlight 中编辑并继续?

c# - 带有自定义序列化程序的 JSON.NET 到自定义对象

c# - 无法将字符串转换为字符

c# - 异步拖放到 Windows 资源管理器

c# - WPF中使用INotifyPropertyChanged绑定(bind)系统相关信息

c# - 使用 OPOS 兼容硬件的事件顺序是什么?

.net - Visual Studio Team Services-等待可用的代理

c# - 如何中断现有的 IObservable 序列?

c# - 修饰符 public 对此项目无效