I have been trying to use MEF on a new project and am having some difficulty getting imports to work, which I cannot explain why. I am following the samples on MSDN and elsewhere, but they are not working for me. This is using MEF 4.0 in a .NET 4 project.
I have defined a simple contract:
public interface ICommand
{
int Execute(string[] args);
}
I implemented some parts and added some metadata:
[Export(typeof(ICommand))]
[ExportMetadata("Name", "init")]
public class InitCommand : ICommand { ... }
[Export(typeof(ICommand))]
[ExportMetadata("Category", "service")]
[ExportMetadata("Name", "start")]
public class StartServiceCommand : ICommand { ... }
I defined the following metadata interface:
public interface ICommandMetadata
{
[DefaultValue(null)]
string Category { get; }
string Name { get; }
}
In my main program, I am creating a catalog-based export provider and then trying to compose the main program object:
internal class Program
{
[ImportMany]
private IEnumerabe<Lazy<ICommand, ICommandMetadata>> commands;
private static int Main(string[] args)
{
var assembly = Assembly.GetExecutingAssembly();
var assemblyExportProvider = new CatalogExportProvider(new AssemblyCatalog(assembly));
var compositionContainer = new CompositionContainer(assemblyExportProvider);
assemblyExportProvider.SourceProvider = compositionContainer;
var batch = new CompositionBatch();
batch.AddPart(this);
compositionContainer.Compose(batch);
return 0;
}
}
When I run the above code, this works as expected and both parts are resolved. When I go a step further and create a custom export attribute, the code stops working. Here's my custom metadata attribute and updated parts:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[MetadataAttribute]
public sealed class CommandAttribute : ExportAttribute
{
public CommandAttribute() : base(typeof(ICommand))
{
}
[DefaultValue(null)]
public string Category { get; set; }
public string Name { get; set; }
}
[Command(Name = "init")]
public class InitCommand : ICommand { ... }
[Command(Category = "service", Name = "start")]
public class StartServiceCommand : ICommand { ... }
By applying the custom export attribute, my commands collection in my program is an empty array. I played around with this some more, and I found that if I change the properties in the metadata interface to arrays of strings, the importing works again:
public interface ICommandMetadata
{
[DefaultValue(null)]
string[] Category { get; }
string[] Name { get; }
}
Can anyone tell me if I am doing something wrong? Why does this only work if I use arrays in the metadata interface? Is there a way to make this work without using arrays for the properties?
Thanks in advance for your help.