2
votes

I haven't been able to find an answer for my problem. I'm using MEF to find and create my classes that implement IPlugIn, but I end up with two versions of each PlugIn class. I have determined that the AggregateCatalog only contains one Assembly that contains only 1 type of each class as a Part, but I am still getting two instances of each as the end result. I'm probably just doing something stupid, but I haven't found it yet. I'd appreciate any help...


...

    [ImportMany(typeof(IPlugIn))]
     public System.Lazy>[] Plugins { get; set; }

...
    //aggregatecatalog only contains one dll containing plugin classes, 4 of them
    container = new CompositionContainer(aggregateCatalog,
                                         CompositionOptions.DisableSilentRejection 
                                         | CompositionOptions.IsThreadSafe);\

    container.SatisfyImportsOnce(this);

    ...
    public void StartAll()
    {
    //We have 8 PlugIns here?? How? 
    if (Plugins == null || Plugins.Count() == 0)
    {

       log.Warn("No PlugIns Available to Start!");
       return;
    }

        foreach (var plug in Plugins)
        {
            log.Info("Starting PlugIn: " + plug.Value.GetName());
            plug.Value.Start();
        }
    }

   ...

    [Export(typeof(IPlugIn))]
    public class MyPlugIn : BasePlugIn, IPlugIn

    ...

I'm debugging in Visual Studio. I clearly see only one Assembly loading. The CompositionContainer has only 1 of each. After SatisfyImportOnce in StartAll(), I have two instances of each IPlugIn classes. Is this something with the way I am using ImportMany? I am open to any ideas.

2
What do your exports look like? I've had this happen to me when my export statements weren't setup correctly.burnttoast11
I added an example of my Export. You see any problem with it?chrislhardin
First, your BasePlugIn and IPlugIn don't have an Export tag, do they? Next, something you could try is removing the typeof(IPlugIn) from your Export and ImportMany. Don't know why that would help, but I noticed I don't have that on my Exports and ImportManys.burnttoast11
try replacing container.SatisfyImportsOnce(this) with container.ComposeParts(this). I'm not familiar with SatisfyImportsOnce, but I use ComposeParts all the time with importmany.dthorpe
I've tried ComposeParts before and still same issue. I should have mentioned that. No BasePlugIn and IPlugIn do not have Export. removing typeof had no effect. I still get two instances of each class... weird stuff...any other ideas?chrislhardin

2 Answers

3
votes

The solution turned out to be simple. I removed the [InheritedExport] from the IPlugIn interface completely and that created the correct number of plugins. If I removed the [Export... from each PlugIn subclass, I got no plugins at all. It was the combination of the two that created the multiple instances.

2
votes

If you have an InheritedExport attribute on your interface, you must use an InheritedExport on your class that implements the interface. Applying Export results in an additional part being composed, which is what you found out.

Also, if you want to apply any other ExportMetadata to a class that implements an interface with InheritedExport, you must add the InheritedExport attribute again in order to add the metadata (replacing the inherited metadata, even if there is none). This is not addressed in the MSDN documentation for InheritedExport or ExportMetadata, but I ran across some vague references in other obscure Microsoft documentation.