Contract implementation is silently excluded from an ImportMany property collection

Aug 9, 2015 at 12:20 AM
How can I programatically determine when a contract implementation is silently excluded from an ImportMany property collection due to an unfulfilled contract inside the implementation?

Consider a contract implementation that has an Import property contract which remains unfulfilled:
[Export(typeof(IAction))]
class Action2 : IAction
{
    [Import(typeof(INotImplemented))]
    public INotImplemented NotImplemented { get; set; }
    void IAction.Run() { Console.WriteLine("Action2 completed."); }
}
Due to the unfulfilled contract on the property, this implementation does not appear in any ImportMany collections:
[ImportMany]
public IEnumerable<IAction> Actions { get; set; }
This behavior is understandable, but presents a problem. The implementation is missing silently. There are no error messages from the composition engine.

I would like an exception to be thrown if any contracts are unfulfilled.

My question is:
How do I determine when an implementation of a contract is excluded from an ImportMany collection due to an unfulfilled Import property contract?

The following example shows the behavior I'm describing:
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;

namespace DemoConsole
{
    class Program
    {
        //This contract is implemented by Action1 and Action2
        interface IAction
        {
            void Run();
        }

        //This contract has no implementation
        interface INotImplemented { }

        [Export(typeof(IAction))]
        class Action1 : IAction
        {
            void IAction.Run() { Console.WriteLine("Action1 completed."); }
        }

        [Export(typeof(IAction))]
        class Action2 : IAction
        {
            //This property contract remains unfulfilled
            [Import(typeof(INotImplemented))]
            public INotImplemented NotImplemented { get; set; }

            void IAction.Run() { Console.WriteLine("Action2 completed."); }
        }

        //This collection excludes Action2 due to an unfulfilled property contract
        [ImportMany]
        IEnumerable<IAction> Actions { get; set; }

        static void Main(string[] args)
        {
            var p = new Program();

            //My question is: How do I get the CompositionContainer to give a
            //warning when Action2 is excluded from the ImportMany Actions collection
            //property on the Program class?
            var catalog = new AssemblyCatalog(typeof(Program).Assembly);
            var container = new CompositionContainer(catalog);
            container.ComposeParts(p);

            //Action2 is excluded from the ImportMany Actions collection
            //property on the Program class
            Console.WriteLine("Action count: {0}", p.Actions.Count());
            foreach (var action in p.Actions)
                action.Run();

            //Console output is:
            //Action count: 1
            //Action1 completed

            Console.ReadLine();
        }
    }
}