Reputation: 2820
I have been trying to teach myself MEF, starting with this tutorial:
There are some differences from the way MEF works now compared to the way it seems to work in this tutorial. One difference is the CompositionBatch object; however, I think I understand the changes that were made.
One difference I can't seem to understand, though, is that whereas the tutorial says I should be able to handle 0/1/multiple imports by changing the return type of a property, I can't make this work in practice. Below I will paste the code that is giving me an error; can anyone enlighten me as to why this doesn't work and what I should do instead?
I will eventually be using MEF to create a plugin-based application that will have different functionality added at runtime by dropping different .dll files that implement a certain interface into a directory. I think I'll be using the DirectoryCatalog for that, but I think I need to understand this hurdle first.
namespace MessinWithMef
{
class Program
{
[Import]
public IEnumerable<string> Message { get; set; }
public void Run()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var batch = new CompositionBatch();
batch.AddPart(this);
var container = new CompositionContainer(catalog);
container.Compose(batch);
foreach (var s in Message)
{
Console.WriteLine(s);
}
Console.ReadKey();
}
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
}
public class SimpleHello
{
[Export]
public string Message
{
get
{
return "Hello world!";
}
}
}
public class ExtraHello
{
[Export]
public string OtherMessage
{
get
{
return "Hi there!";
}
}
}
}
Here's the text of the error:
The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) No valid exports were found that match the constraint '((exportDefinition.ContractName == "System.Collections.Generic.IEnumerable(System.String)") AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso "System.Collections.Generic.IEnumerable(System.String)".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))', invalid exports may have been rejected.
Resulting in: Cannot set import 'MessinWithMef.Program.Message (ContractName="System.Collections.Generic.IEnumerable(System.String)")' on part 'MessinWithMef.Program'.
Element: MessinWithMef.Program.Message (ContractName="System.Collections.Generic.IEnumerable(System.String)") --> MessinWithMef.Program
Upvotes: 4
Views: 926
Reputation: 27515
You have to use [ImportMany]
if you want to resolve multiple matching Exports.
Note that, in a Plugin type of scenario, you'll probably want to use ExportMetadata and then decide which of the Plugins you actually want to instantiate. You would then do something like:
[ImportMany]
IEnumerable<Lazy<IPlugin, IPluginMetadata>> _possiblePlugins;
Now your code can enumerate the possible plugins, examine the metadata, and then decide whether or not to instantiate each Lazy import.
Upvotes: 3