Discover plugin using ExportMetaData attribute.

Jul 15, 2011 at 8:57 AM


In the below code I discover all the plugins using the contract ICalculator and then pick the plugin depending on the metat data attribute.

I need to discover the plugin depending on the ExportMetadata attribute  directly and not on the Interface contract type "ICalculator".

Is there any way I can do that?

Thanks!


Here is Plugin Information:

   public abstract class MathOperation : ICalculator
    {
        public abstract int GetNumber(int num1, int num2);      
    }

    [Export(typeof(ICalculator))]
    [ExportMetadata("CalciMetaData", "Add")]
    public class Add : MathOperation
    {
        #region Interface members
        public override int GetNumber(int num1, int num2)
        {
            return num1 + num2;
        }
        #endregion
    }

    [Export(typeof(ICalculator))]
    [ExportMetadata("CalciMetaData", "Divide")]
    public class Divide : MathOperation
    {
        #region Interface members
        public override int GetNumber(int num1, int num2)
        {
            return num1 / num2;
        }
        #endregion
    }
// Composition.
 public class CalciCompositionHelper
    {
        [ImportMany]
        public System.Lazy<ICalculator, IDictionary<string, object>>[] CalciPlugins { get; set; }

        /// <summary>
        /// Assembles the calculator components
        /// </summary>
        public void AssembleCalculatorComponents()
        {
            try
            {
                //Step 1: Initializes a new instance of the 
                //        System.ComponentModel.Composition.Hosting.AssemblyCatalog class with the 
                //        current executing assembly.
                var catalog = new AssemblyCatalog(Assembly.LoadFrom(@"D:\Study\MEF_Program_Files\Files\SimpleCalculator-Part2\CalculatorUI\CalculatorFactory\bin\Debug\CalculatorFactory.dll"));

                //Step 2: The assemblies obtained in step 1 are added to the CompositionContainer
                var container = new CompositionContainer(catalog);

                //Step 3: Composable parts are created here i.e. the Import and Export components 
                //        assembles here
                container.ComposeParts(this);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Sends the result back to the client
        /// </summary>
        /// <param name="num1"></param>
        /// <param name="num2"></param>
        /// <returns></returns>
        public int GetResult(int num1, int num2, string operationType)
        {
            int result = 0;
            foreach (var CalciPlugin in CalciPlugins)
            {
                if ((string)CalciPlugin.Metadata["CalciMetaData"] == operationType)
                {
                    result = CalciPlugin.Value.GetNumber(num1, num2);
                    break;
                }                               
            }
            return result;           
        }
    }


Aug 1, 2011 at 9:13 PM

So basically you are trying to get all exports, regardless of their contract, purely based on the metadata? While technically this is possible, this is not exposed via any part-level API, and for a fairly good reason - when you get all values based on the criteria that you have mentioned, what are you going to do with them? As there's no contract compliance, you can't "call" into them as they are effectively different things; there's no way to treat them uniformly; also a query like that qould be a very bad performance hit on the underlying catalog, as everything in MEF is optimized for contract-based querying. What exactly are you trying to achieve?