I was very surprised to get this error today, as it’s one that I’ve never encountered before. Everything in the code looked okay, so I did some searches. The previous questions and their respective answers didn’t help.
This one was solved when the poster made sure his assembly references were consistent. I don’t have this issue right now because I’m currently referencing another project in my solution.
This one was solved when the poster was instructed to use ImportMany, but I am already using it (I think properly, too) to try to load multiple plugins
This one was solved when the poster realized that there was a platform target mismatch. I’ve already gone through my projects to ensure that everything targets x86.
So here’s what I am trying to do. I have a plugin that owns a connection to a device. I might also need to be able to share that connection with another plugin. I decided that the cleanest way to do this was to create an interface that would allow the slave plugin to request its own connection to the device. Let’s just call it IConnectionSharer. If the slave plugin does not need to borrow this connection and has its own, then it should use its own implementation of IConnectionSharer to connect to the device.
My “master” plugin (the one that owns the connection to the device) implements IConnectionSharer. It also exports this via ExportAttribute.
My “slave” plugin assembly defines a class that also implements and exports IConnectionSharer.
When the application loads, the intent is for my slave plugin, via MEF, to enumerate all IConnectionSharers and store them in an IEnumerable<IConnectionSharer>. It does so like this:
[ImportMany]
public IEnumerable<IConnectionSharer> AllSharedConnections { get; set; }
Nicholas asked me to show my Exports, so here they are.
“Master” plugin:
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(Interface1))]
[Export(typeof(Interface2))]
[Export(typeof(Interface3))]
[Export(typeof(IConnectionSharer))]
public partial class MasterPlugin : Interface1, Interface2, Interface3, IConnectionSharer
{
...
}
“Slave” plugin:
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(Interface1))]
public class SlavePlugin : Interface1
{
private Model _model { get; set; }
private ViewModel _viewmodel { get; set; }
[ImportingConstructor]
public SlavePlugin( [Import] Model model)
{
_model = model;
_viewmodel = new ViewModel( model);
}
}
Model:
[Export(typeof(Model))]
public class Model
{
[ImportMany(typeof(IConnectionSharer))]
private IEnumerable<IConnectionSharer> AllSharedConnections { get; set; }
...
}
IConnectionSharer implementation internal to “slave” plugin:
[Export(typeof(IConnectionSharer))]
public class PrivateConnection : IConnectionSharer
{
...
}
But during part composition, I get the error the export ‘Company.MasterPlugin (ContractName=”IConnectionSharer”)’ is not assignable to type ‘IConnectionSharer’.
The error message itself seems clear enough — it’s as if MEF thinks my master plugin doesn’t inherit from IConnectionSharer… but it does! Can anyone suggest further debugging strategies? I’m going to start the painful process of single stepping through the MEF source.
UPDATE
This is an interesting clue — if, after clearing out my output folder and rebuilding the solution, I delete the “master” plugin (so that the “slave” plugin will use its own IConnectionSharer object), my application loads just fine, and my slave plugin also behaves as expected. If I put the master plugin back into the plugins folder, I get the MEF composition problem again.
I also thought I’d try to use Lazy<> instantiation to see if that had any effect. The result was a little startling. MEF complains with this error: Cannot populate the collection ‘AllSharedConnections’ because it does not implement ICollection or is read-only. If the collection is not IEnumerable<T> or T[] it must implement ICollection and be either pre-initialized or be writable with a default constructor.
HUH? Clearly AllSharedConnections is an IEnumerable<T>, so why is MEF complaining?
You most likely have an old version of an assembly lying around in your output folder, e.g. after a rename. Normally this is not a problem because no other assemblies reference this old one. With MEF however, assemblies can be picked up for the composition just by being present in the application folder.
Clean up your output folder, rebuild and see if the problem goes away.
edit: since the problem doesn’t go away when you clean up your output folder, my next guess would be that you have two declarations of
IConnectionSharer, or you are compiling the same code into two different assemblies. This will result in twoIConnectionSharerinterfaces with the same name but a different identity.