Search code examples
c#mef

Getting exported interface by implementing class name


I have various objects that implement a specific interface. In one place in my code I get all the exports of the interfaces and save the actual class name in a DB. Here's some quick and dirty pseudo:

public interface ISomething { }

[Export(typeof(ISomething))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class Something : ISomething { }

[Export(typeof(ISomething))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class SomethingElse : ISomething { }

public class Handler {

    [Import]
    CompositionContainer _container;

    [ImportMany]
    IEnumerable<ISomething> _somethings;

    public void SaveSomething() {
        foreach(ISomething something in _somethings) {
            string className = something.GetType().Fullname;
            SaveToDatabase(className);
        }
    }
}

This works just fine and I can easily get all the ISomething implementations. However, I also need to get a new instance of a specific classname at a later point.

If I try _container.GetExportedValues<ISomething> I get both Something and SomethingElse. If I try _container.GetExportedValue<ISomething>("SomethingElse") I get a composition error saying that it can't find any exports that match the constraint.

So, how can I get a new instance of SomethingElse by only knowing name of the class?


Solution

  • You can provide two export attributes, so that you can import either by interface name or by your custom name.

    Something like this:

    public interface ISomething { }
    
    [Export(typeof(ISomething))]
    [Export("Something", typeof(ISomething))]
    public class Something : ISomething { }
    
    [Export(typeof(ISomething))]
    [Export("SomethingElse", typeof(ISomething))]
    public class SomethingElse : ISomething { }
    

    Now, you can do this:

    class Test
    {
        [ImportMany]
        IEnumerable<ISomething> _somethings;
    
        [Import("SomethingElse", typeof(ISomething))]
        SomethingElse _somethingElse;
    }