MEF ExportFactory <t> - 如何正确处理长期运行的应用程序?</t>

时间:2011-07-01 12:54:27

标签: c# memory-management mef factory object-lifetime

基本上,是否有一种简单的方法来处理由ExportFactory<T>创建的导入?我问的原因是因为导出通常包含对仍然存在的东西的引用,例如EventAggregator。我不想遇到这样的问题,即我创造了数百个这样的问题,并且在没有必要时让它们存在。

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

1 个答案:

答案 0 :(得分:0)

当您在Dispose上致电ExportLifetimeContext<T>时,它会在参与创建NonShared的任何T部分致电处置。它不会处置任何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();
    }
}

但是因为您的类型无法看到导入的IBar实例是Shared还是NonShared,您可能会面临处置共享组件的风险。

我认为挂在ExportedLifetimeContext<T>的实例上是实现目标的唯一安全方式。

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

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.
  }
}

感觉有点脏......