MEF: difference between GetExportedValue and SatisfyImports

We use MEF (.NET 4, we cannot use 4.5 at the moment) in the MVVM application. Everything was fine until we needed to create models on the fly, for example, editable table rows. I do not want to work in memory leaks, I found this article http://pglazkov.blogspot.ch/2011/04/mvvm-with-mef-viewmodelfactory.html and I found an unexpected behavior that I would like to understand. This is an item added to the Shell.Items collection:

[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--; } } [..] } 

And this is the factory:

 [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; } } [..] } 

If I use this code, Item is along with the child container. If I change it to:

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

The item is no longer placed in the container. I would like to understand if it is dangerous to use the GetExportedValue method (I use this method in other parts of the application) and which is the best practice to avoid memory leaks with for viewing models with short lifetimes.

Any help appreciated

+4
source share
1 answer

As far as I know (experimenting and looking at the MEF source code ):

  • When the container is located, all exported parts of the catalog that are disposable are also deleted. The exported parts of the catalog are either decorated with ExportAttribute, or are listed as exported using RegistrationBuilder (MEF2). These parts are created by the container, and their lifetime depends on the lifetime of the container itself.
  • On the other hand, manually created objects created using CompositionContainer.SatisfyImportsOnce or CompositionContainer.ComposeParts will not be disposed of. Their service life does not depend on the service life of the container.

Now the difference between GetExportedValue and SatisfyImports is not the same. GetExportedValue returns all exported parts registered in the container. This includes parts created by the container (exported catalog parts mentioned in 1.), as well as parts registered using CompositionContainer.ComposeParts. SatisfyImports will enter any goods it imports, but will not register the object as an export, even if its class is marked as an exported type (see 1.). In addition, SatisfyImports will disable re-layout, but this is not the topic.

The MEF CodePlex documentation provides valuable information about the Hours of Life .

+7
source

Source: https://habr.com/ru/post/1497798/


All Articles