MEF ExportFactory- 如何在长时间运行的应用程序中正确处置?

发布于 2024-11-18 05:06:01 字数 407 浏览 8 评论 0原文

基本上,是否有一种简单的方法来处理由 ExportFactory 创建的导入?我问的原因是因为导出通常包含对仍然存在的内容的引用,例如 EventAggregator。我不想遇到这样的问题:我创建了数百个这样的东西,并在不需要时将它们闲置。

我注意到,当我创建对象时,我会返回一个带有 Dispose 的 ExportLifetimeContext 。但是,我不想将 ExportLifetimeContext 传回请求 ViewModel 副本的 ViewModel,因此我传回值。 (return Factory.Single(v => v.Metadata.Name.Equals(name)).CreateExport().Value;)

Basically, is there an easy way to dispose of the imports that are created by an ExportFactory<T>? The reason I ask is because the exports usually contain a reference to something that is still around, such as the EventAggregator. I don't want to run into the issue where I'm creating hundreds of these and leaving them laying around when they are not necessary.

I noticed that when I create the objects I get back a ExportLifetimeContext<T> which carries a Dispose with it. But, I don't want to pass back an ExportLifetimeContext to my ViewModels requesting copies of the ViewModel, hence I pass back the Value. (return Factory.Single(v => v.Metadata.Name.Equals(name)).CreateExport().Value;)

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

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

发布评论

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

评论(1

旧城烟雨 2024-11-25 05:06:01

当您对 ExportLifetimeContext 调用 Dispose 时,它将对参与创建 T 的任何 NonShared 部分调用 dispose代码>.它不会处置任何Shared组件。这是一种安全的行为,因为如果 NonShared 部分纯粹是为了满足 T 的导入而实例化的,那么它们可以安全地被处置,因为它们不会被任何人使用其他进口。

我认为您可以实现它的唯一其他方法是自定义 Dispose 方法,将 dispose 调用链接到您导入的任何其他成员属性,例如:

[Export(typeof(IFoo))]
public class Foo : IFoo, IDisposable
{
    [Import]
    public IBar Bar { get; set; }

    public void Dispose()
    {
        var barDisposable = Bar as IDisposable;
        if (barDisposable != null) 
            barDisposable.Dispose();
    }
}

But as您的类型不知道导入的 IBar 实例是 Shared 还是 NonShared 您面临处置共享组件的风险。

我认为挂在 ExportedLifetimeContext 实例上是实现您想要的目标的唯一安全方法。

不确定这是否有帮助,感觉像是不必要的包装,但你可能:

public class ExportWrapper<T> : IDisposable
{
  private readonly ExportLifetimeContext<T> context;

  public ExportWrapper<T>(ExportLifetimeContext<T> context)
  {
    this.context = context;
  }

  public T Value 
  {
    get { return context.Value; }
  }

  public void Dispose()
  {
    context.Dispose();
  }

  public static implicit operator T(ExportWrapper<T> wrapper)
  {
    return wrapper.Value;
  }

  public static implicit operator ExportWrapper<T>(ExportLifetimeContext<T> context)
  {
    return new ExportWrapper<T>(context);
  }
}

你可能:

[Import(typeof(IBar))]
public ExportFactory<IBar> BarFactory { get; set; }

public void DoSomethingWithBar()
{
  using (ExportWrapper<IBar> wrapper = BarFactory.CreateExport())
  {
    IBar value = wrapper;
    // Do something with IBar;
    // IBar and NonShared imports will be disposed of after this call finishes.
  }
}

感觉有点脏......

When you call Dispose on an ExportLifetimeContext<T> it will call dispose on any NonShared part involved in the creation of T. It won't dispose of any Shared components. This is a safe behaviour, because if the NonShared parts were instantiated purely to satisfy the imports for T, then they can safely be disposed as they won't be used by any other imports.

The only other way I think you could achieve it, would be to customise the Dispose method to chain the dispose call to any other member properties you import with, e.g.:

[Export(typeof(IFoo))]
public class Foo : IFoo, IDisposable
{
    [Import]
    public IBar Bar { get; set; }

    public void Dispose()
    {
        var barDisposable = Bar as IDisposable;
        if (barDisposable != null) 
            barDisposable.Dispose();
    }
}

But as your type has no visibility of whether the imported instance of IBar is Shared or NonShared you run the risk of disposing of shared components.

I think hanging onto the instance of ExportedLifetimeContext<T> is the only safe way of achieving what you want.

Not sure if this helps, feels like unnecessary wrapping, but could you possibly:

public class ExportWrapper<T> : IDisposable
{
  private readonly ExportLifetimeContext<T> context;

  public ExportWrapper<T>(ExportLifetimeContext<T> context)
  {
    this.context = context;
  }

  public T Value 
  {
    get { return context.Value; }
  }

  public void Dispose()
  {
    context.Dispose();
  }

  public static implicit operator T(ExportWrapper<T> wrapper)
  {
    return wrapper.Value;
  }

  public static implicit operator ExportWrapper<T>(ExportLifetimeContext<T> context)
  {
    return new ExportWrapper<T>(context);
  }
}

Which you could possibly:

[Import(typeof(IBar))]
public ExportFactory<IBar> BarFactory { get; set; }

public void DoSomethingWithBar()
{
  using (ExportWrapper<IBar> wrapper = BarFactory.CreateExport())
  {
    IBar value = wrapper;
    // Do something with IBar;
    // IBar and NonShared imports will be disposed of after this call finishes.
  }
}

Feels a bit dirty...

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