Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>+1 for the question - I hadn't had a chance to look at MEF since 4.5 came out so it forced me to get up to speed with the newly added <code>RegistrationBuilder</code> class!</p> <p>I'm guessing the reason your example doesn't work is because as I understand it, the <code>RegistrationBuilder</code> is designed to replace the role of attributes that MEF relies on so heavily up to .NET 4.0. The <code>ExportMetadataAttribute</code> is part of the old way of doing things, and it's just my guess that the old and new don't play well together.</p> <p>Thanks to the addition of <code>RegistrationBuilder</code> you can achieve exactly what you want without the exported classes having any knowledge that they are being constructed using MEF. In my opinion this is a vast improvement in MEF from 4.0.</p> <p>First let us start with the classes we want to export. First of all I define the <code>MyMetadataAttribute</code> class, which encapsulates the metadata associated to the type we will want to filter on:</p> <pre><code>public enum MyClassType { TypeOne, TypeTwo } [AttributeUsage(AttributeTargets.Class)] public class MyMetadataAttribute: Attribute { public MyMetadataAttribute(MyClassType type) { Type = type; } public MyClassType Type { get; private set; } } </code></pre> <p>Now come the classes that I potentially want to export:</p> <pre><code>public interface IClass { } [MyMetadata(MyClassType.TypeOne)] public class MyClassA : IClass { public MyClassType Type { get { return MyClassType.TypeOne; } } } [MyMetadata(MyClassType.TypeTwo)] public class MyClassB : IClass { public MyClassType Type { get { return MyClassType.TypeTwo; } } } </code></pre> <p>The key to solving your problem is the <code>ForTypesMatching()</code> method on <code>RegistrationBuilder</code>. The argument is a predicate that takes the type and returns true or false depending on whether you want to include the type in the exported results. The code below demonstrates an example of this:</p> <pre><code>internal class Program { private static void Main(string[] args) { var registrationBuilder = new RegistrationBuilder(); registrationBuilder .ForTypesMatching&lt;IClass&gt;(t =&gt; FilterOnMetadata(t, MyClassType.TypeOne)) .ExportInterfaces(); var assemblyCatalog = new AssemblyCatalog(typeof (MyClassType).Assembly, registrationBuilder); var compositionContainer = new CompositionContainer(assemblyCatalog); var ic = new TestImportContainer(); compositionContainer.ComposeParts(ic); var count = ic.ImportedParts.Count(); } public static bool FilterOnMetadata(Type t, MyClassType classType) { var metadataAttribute = (MyMetadataAttribute) t.GetCustomAttributes(true) .SingleOrDefault(at =&gt; at is MyMetadataAttribute); if (metadataAttribute != null) return metadataAttribute.Type == classType; return false; } private sealed class TestImportContainer { [ImportMany(typeof(IClass))] public IEnumerable&lt;IClass&gt; ImportedParts { get; set; } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload