Search code examples
c#mef

MEF getting exports with a string


Is it possible to get exports by only have a string? The parts are in the container but I only have a string to resolve the correct part. MEF seems to want types to resolve, and things like Type.GetType() require a hard reference. Can't use a generic interface, need very specific parts.

The string can be changed to match what ever is needed. (I think)

container.GetExports("ClassLibrary1.Class1")

I haven't played with the metadata stuff but can you resolve based on a metadata string?

Thanks


Solution

  • If you're trying to get parts without a reference to the type, what are you hoping to accomplish with the part once you have it? Also note that you can reference a type without an object using typeof or by using generic methods.

    This is why MEF is usually wired up using public interfaces, rather than concrete and/or nonpublic types.

    What you're looking for is the default Contract Name for a given type, however any helper methods for looking up that default name will require the Type object and fall under the same explanation as above.

    EDIT: The above applies if you're trying to find the contract name for a given class. For differentiating exports of the same type, see below

    When exporting, you can specify both a contract name and export type, such as

    [Export("Contract", typeof(IInterface))]
    public class Part : IInterface { /*...*/ }
    

    This can allow you to differentiate between multiple parts. If you want the part imported as part of an ImportMany directive, you must also export it without a contract name, such as

    [Export("Contract", typeof(IInterface))]
    [Export(typeof(IInterface))]
    public class Part : IInterface { /*...*/ }
    

    Since attributes are allowed to take const values, it may also be useful to specify the individual contract names in a collection of names, IE

    public static class ContractNames
    {
        public const string Contract = "Contract";
    }
    
    [Export(ContractNames.Contract, typeof(IInterface))]
    [Export(typeof(IInterface))]
    public class Part : IInterface { /*...*/ }
    
    ...
        container.GetExportedValue<IInterface>(ContractNames.Contract);
    

    Note the above uses GetExportedValue instead of GetExports since the former will directly compose and return values, instead of export metadata