Bruno Shine
Bruno Shine

Reputation: 1031

ASP.NET MVC + MEF + MefContrib: Can't seem to get metadata from Exports

I'm using asp.net mvc3 with MEF + MEFContrib to load some services on my controllers. What's happening is that I can load the services - IEnumerable<IPublishService> publishers - with the [ImportingConstructor] but when I try to load the services with metadata - Lazy<IPublishService, IPluginMetaData>[] publishers - I get an empty array.

Any thoughts on why? Thanks.

My code:

public interface IPluginMetaData
{
    string Name { get; }
    string Version { get; }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginMetadataAttribute : ExportAttribute
{
    public PluginMetadataAttribute(string name, string version)
        : base(typeof(IPluginMetaData))
    {
        Name = name;
        Version = version;
    }

    public string Name { get; set; }
    public string Version { get; set; }
}

[Export(typeof(IPublishService))]
[PluginMetadata("Default", "1.0.0.0")]
public class SamplePublishService : IPublishService
{

}

[ImportingConstructor]
public HomeController(Lazy<IPublishService, IPluginMetaData>[] publisher /* Empty Array */ , IEnumerable<IPublishService> publishers /* Array with 1 service */)
{
}

UPDATE (based on Daniel answer but still nothing)

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginMetadataAttribute : ExportAttribute
{
    public PluginMetadataAttribute(string name, string version)
        : base(typeof(IPublishService))
    {
        Name = name;
        Version = version;
    }

    public string Name { get; set; }
    public string Version { get; set; }
}

[PluginMetadata("Default", "1.0.0.0")]
public class GoogleSampleGroupPublishService : IPublishService
{
}

[ImportingConstructor]
public HomeController([ImportManyAttribute]Lazy<IPublishService, IPluginMetaData>[] publisher)
{
}

Upvotes: 1

Views: 625

Answers (1)

Daniel Plaisted
Daniel Plaisted

Reputation: 16744

Normally, you would need to put an ImportManyAttribute on the arguments to your constructor, since they are collection imports. Since one of them is working, I suspect that MEFContrib is doing something so that you don't need to do this, but it only works for IEnumerable<T> and not an array of T. So try changing the first argument to IEnumerable<Lazy<IPublishService, IPluginMetadata>>, or adding an ImportManyAttribute in front of it.

Some other issues I noticed: Your PluginMetadataAttribute is derived from ExportAttribute. The reason you would do that is so that you don't have to put both an export and a metadata attribute on your services. However, the type that you pass to the base class constructor is the exported contract. So this should be IPublishService instead of IPluginMetadata. Make that change and remove the Export attribute from SamplePublishService.

Upvotes: 1

Related Questions