I've been experimenting with MEF, and I noticed I occasionally get duplicate exports. I've created this simplified example:
I have created the following interfaces, and an attribute for the metadata:
public interface IItemInterface
{
string Name { get; }
}
public interface IItemMetadata
{
string TypeOf { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false)]
public class ItemTypeAttribute : ExportAttribute, IItemMetadata
{
public ItemTypeAttribute(string typeOf)
{
TypeOf = typeOf;
}
public string TypeOf { get; set; }
}
I then created the following exports:
public class ExportGen : IItemInterface
{
public ExportGen(string name)
{
Name = name;
}
public string Name
{
get;
set;
}
}
[Export(typeof(IItemInterface))]
[ItemType("1")]
public class Export1 : ExportGen
{
public Export1()
: base("Export 1")
{ }
}
public class ExportGenerator
{
[Export(typeof(IItemInterface))]
[ExportMetadata("TypeOf", "2")]
public IItemInterface Export2
{
get
{
return new ExportGen("Export 2");
}
}
[Export(typeof(IItemInterface))]
[ItemType("3")]
public IItemInterface Export3
{
get
{
return new ExportGen("Export 3");
}
}
}
Execute this code:
AggregateCatalog catalog = new AggregateCatalog();
CompositionContainer container = new CompositionContainer(catalog);
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly().CodeBase));
var exports = container.GetExports<IItemInterface, IItemMetadata>();
foreach (var export in exports)
{
Console.WriteLine(String.Format("Type: {0} Name: {1}", export.Metadata.TypeOf, export.Value.Name));
}
This outputs:
Type: 1 Name: Export 1 Type: 2 Name: Export 2 Type: 3 Name: Export 3 Type: 3 Name: Export 3
When I call GetExports() I get a duplicate of Export3, exports 1 and 2 are not duplicated. (Notice when I use the ItemTypeAttribute I get the duplicate.)
If I remove type 1 and 2, and call "GetExport" it throws an exception because there are more than 1 export.
A google search yielded a single blog post from a year ago, but there was no resolution or follow-up
Am I doing something wrong here, or possibly missing something silly?
(All this is using VS2010 and .NET 4.0.)
Change the constructor of ItemTypeAttribute
to:
public ItemTypeAttribute(string typeOf)
: base(typeof(IItemInterface))
{
TypeOf = typeOf;
}
and remove the
[Export(typeof(IItemInterface))]
since your custom attribute is derived from ExportAttribute
. This explains your double exports.
Guidelines can be found on section "Using a Custom Export Attribute" from MEF's Documentation in CodePlex.