Search code examples
c#mef

Is ctor(IDictionary<,>) required for MEF custom attribute classes


I got a CompositionContractMistachException when using a custom attribute class in MEF on .NET 4.0.

Unable to create an instance of the Metadata view '(snip).ModuleExportAttribute, (snip), Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because a constructor could not be selected. Ensure that the type implements a constructor which takes an argument of type IDictionary<string, object>.

Here is my ModuleExportAttribute class, nothing special:

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class ModuleExportAttribute : ExportAttribute
{
    public ModuleExportAttribute(string name) : base(typeof(IModule))
    {
        this.Name = name;
    }

    public string Name { get; private set; }
}

The usage is like this:

[ModuleExport("MyModule")]
public class MyModule : IModule
{ 
   ...
}

After adding the asked constructor, the exception goes away.

However, I couldn't find any reference that states this requirement. On the opposite, I saw many examples and blog posts using custom attribute class without such constructor. Am I missing something here?


Solution

  • How are you trying to import this? I suspect the error is caused by you importing something like Lazy<IModule, MetadataExportAttribute> in which case yes in order to use a concrete type as the metadata type it must either be an interface, in which case we generate a proxy type or it must be a type that takes an IDictionary<string,object> so that the metadata can be passed to it.

    Try something like:

    public interface IModuleMetadata
    {
      string Name { get; }
    }
    

    Then change your import to something like:

    [Import]
    Lazy<IModule, IModuleMetadata> Module;
    

    I also like to have my ExportAttribute implement the IModuleMetadata interface to make sure they stay consistent but that isn't absolutely necessary.