why ViewModelRepository implement IPartImportsSatisfiedNotification interface?

Jul 28, 2010 at 12:02 PM
Edited Jul 28, 2010 at 12:02 PM

in file ViewModelRepoitory.cs:

public class ViewModelRepository : IPartImportsSatisfiedNotification
{

......

 #region IPartImportsSatisfiedNotification Members

        public void OnImportsSatisfied()
        {


.......

 

       }

 

#endregion

......

 

I don't know why ViewModelRepository inherit from IPartImportsSatisfiedNotification? ViewModelRepository is not a ComposablePart, So I don't know who will call the OnImportsSatisfied ?

could you give a sample?

Thanks!.

Coordinator
Jul 28, 2010 at 12:45 PM
MEFedMVVM handles recomposition so that it tries to satisfy any ViewModels that were not resolved before... Example. If you have a view that needs a ViewModel (that view model is not in the composition yet because it is in some plugin). When recomposition happens MEFedMVVM will try to inject the ViewModel if it is now present in the new composition
Jul 28, 2010 at 2:23 PM
Edited Jul 28, 2010 at 2:30 PM

Thanks for your replay!

But I don't find a line code in MEFedMVVM that will directly or indirectly to call the ViewModelRepository's OnImportsSatisfied.

If ViewModelRepository has a Import or Export, I Know MEF will treat it as a ComposablePart, so MEF will call it like below:

in class System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart:

[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void NotifyImportSatisfied()
        {
            if (this._invokeImportsSatisfied && !this._invokingImportsSatisfied)
            {
                IPartImportsSatisfiedNotification notify = this.GetInstanceActivatingIfNeeded() as IPartImportsSatisfiedNotification;
                if (notify != null)
                {
                    try
                    {
                        // Reentrancy on composition notifications is allowed, so set this first to avoid
                        // an infinte loop of notifications.
                        this._invokingImportsSatisfied = true;

                        notify.OnImportsSatisfied();
                    }
                    catch (Exception exception)
                    {
                        throw new ComposablePartException(
                            String.Format(CultureInfo.CurrentCulture,
                                Strings.ReflectionModel_PartOnImportsSatisfiedThrewException,
                                Definition.GetPartType().FullName),
                            Definition.ToElement(),
                            exception);
                    }
                    finally
                    {
                        this._invokingImportsSatisfied = false;
                    }

                    this._invokeImportsSatisfied = false;
                }
            }
        }
        
        
But ViewModelRepository is not a ComposablePart, So will MEF cast ViewModelRepository as IPartImportsSatisfiedNotification and then call it's OnImportsSatisfied? I don't find the code in MEF.

As to MEFedMVVM itself, I only find code in DataContextAwareViewModelInitializer.c

public override void CreateViewModel(Export viewModelContext,
            FrameworkElement containerElement)
        {
        ....
                DependencyPropertyChangedEventHandler handler = null;
                handler = delegate
                {
                    if (containerElement.DataContext != null) // it means we have the VM instance now we should inject the services
                    {
                        resolver.SatisfyImports(containerElement.DataContext, containerElement);
                    }
                    containerElement.DataContextChanged -= handler;
                };

                if (containerElement.DataContext == null)
                    containerElement.DataContextChanged += handler; // we need to wait until the context is set
                else // DataContext is already set
                {
                    handler(null, default(DependencyPropertyChangedEventArgs));
                }
.....
            }
            
like will call ViewModelRepository's OnImportsSatisfied,
But MEFedMVVMResolver.SatisfyImports call Container.SatisfyImportsOnce(attributedPart), the Container is not ViewModelRepository.

So I can't find the source code that will call the ViewModelRepository's OnImportsSatisfied.
Could you give me more clues?

Thanks!

Coordinator
Jul 29, 2010 at 6:59 AM

 

if you implement IPartImportsSatisfiedNotification MEF will call the method of this interface when a recomposition is made (recomposition is when new Types are added to the main composition container).

there is code in that method of the ViewModelRepository... this is the code

public void OnImportsSatisfied()
{
lock (unsatisfiedContracts)
{
for (int i = 0; i < unsatisfiedContracts.Count; i++)
{
var vmContract = unsatisfiedContracts[i];
Debug.WriteLine("MEFEdMVVM: ViewModelRepoistory. Recomposition was made. Will try to recompose missing ViewModel " + vmContract);
var vm = Instance.Resolver.GetViewModelByContract(vmContract.Key, vmContract.Value.IsAlive ? vmContract.Value.Target : null);
if (vm != null)
{
if (vmContract.Value.IsAlive) // if the UI element is still alive
{
AttachViewModelToView(vmContract.Key, (FrameworkElement)vmContract.Value.Target);
}
//remove the item from the list of unsatisfied contracts
unsatisfiedContracts.RemoveAt(i);
i--;
}
}
}
}

 

In that code I am seeing which ViewModel exports where not satisfied and try to satisfy them when there is a recomposition.

With regards to "As to MEFedMVVM itself, I only find code in DataContextAwareViewModelInitializer.c "

This class has nothing to do... that class is there to satisfy the imports on a ViewModel that is not created via MEF (hence the DataContextAware) to read more on DataContextAware ViewModels visit http://marlongrech.wordpress.com/2010/05/23/mefedmvvm-v1-0-explained/

Jul 29, 2010 at 10:56 AM

Thanks for your replay,

 

---------------------------

NET Framework Class Library

IPartImportsSatisfiedNotification Interface

Notifies a part when its imports have been satisfied.

Namespace:  System.ComponentModel.Composition
Assembly:  System.ComponentModel.Composition (in System.ComponentModel.Composition.dll)

---------------------------------------


From the above annotate,  MEF will Notifies a part when it implement IPartImportsSatisfiedNotification Interface, but ViewModelRepository is not a part, because it has no imports or exports or importmany....,

So why MEF will Notifies it?

Could you add a unit test for  ViewModelRepository to MEFedMVVMDemo,  So I can test it?

Thank you very much.