We're using MEF (.NET 4, can't use 4.5 at the moment) in a MVVM application. Everything was fine until we needed to create models on the fly, for instance editable rows of a table. I didn't want to run into memory leaks, I found this article http://pglazkov.blogspot.ch/2011/04/mvvm-with-mef-viewmodelfactory.html and I discovered an unexpected behavior that I would like to understand. This is an Item added to the Shell.Items observable 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, the Item is disposed together 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 not disposed anymore with the container. I would like to understand if it is dangerous to use the GetExportedValue method (I use that method in other parts of the application) and which is the best practice to avoid memory leaks with for view models with a short lifetime.
Any help appreciated