MEF ExportFactory <T>- Как правильно утилизировать в долго работающем приложении? - PullRequest
2 голосов
/ 01 июля 2011

В принципе, существует ли простой способ избавиться от импорта, созданного ExportFactory<T>? Причина, по которой я спрашиваю, заключается в том, что экспорт обычно содержит ссылку на что-то еще, например, EventAggregator. Я не хочу сталкиваться с проблемой, когда я создаю сотни таких и оставляю их лежать, когда они не нужны.

Я заметил, что когда я создаю объекты, я получаю ExportLifetimeContext<T>, который несет с собой Dispose. Но я не хочу передавать ExportLifetimeContext моим ViewModels, запрашивающим копии ViewModel, поэтому я возвращаю значение. (return Factory.Single(v => v.Metadata.Name.Equals(name)).CreateExport().Value;)

1 Ответ

0 голосов
/ 01 июля 2011

Когда вы вызываете Dispose на ExportLifetimeContext<T>, он вызывает dispose для любой 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.
  }
}

Чувствует себя немного грязно ...

...