ImportCardinalityMismatchException

Aug 10, 2009 at 12:39 AM

Sorry to be such a pest today, but getting my system running in Preview 6 is proving a bit problematic.

I'm getting an ImportCardinalityMisMatchException. I basically know what this means, except that I'm getting it on this line of code:

? _compositionContainer.GetExports<T, TMetadataView>()

How can a cardinality mismatch happen on a GetExports? I thought it was a zero to many request and that with stable composition, if anything inside it failed, I'd just have less imported parts in my list.

 

Aug 10, 2009 at 1:36 PM

Your problem is that there probably is an export that has some imports that couldn't been satisfied. So it's not the GetExports() that have the problem, but an import on a specific export. Look at the details of the exception and you'll know what fails.

Aug 10, 2009 at 3:13 PM

OK, I've got this solved, so let me explain boh the problem and offer some hints for avoidign this particular quicksand. 

With stable composition, it was rare that I got an exception, and then only the short string displayed in the Immediate window as I cruised (using something like ToArray) an IEnumerable of the interim list that a custom catalog was returning to the CatalogExportProvider. So,  Mr. Jul's suggestion didn't work for this scenario, although its an obvious first step if you're encountering an error. The team has done a good job of providing detail in exceptions. He's right, do that first, unless Stable Composition is getting in the way (I love Stable Composition, it's just that debugging in it is a headache, and I think we're likely to see better tools for that in future revs).

The problem was that I had not changed all my Import attributes on a couple of IEnumerable to ImportMany, although I thought I had. Some I had overlooked, and some were in ImportingConstructors which I hadn't considered. The first one I encountered happened to use an arbitrary string contract to pull in an IEnumerable of strings. So, the exception was not that MEF was looking for an IEnumerable<IWhatever>, but an arbitrary string, which of course looked correct. I avoided a gigantic rabbit hole by remembering that this code had worked so my code other than MEF issues should not need changing. Note that I got the exception through technique 5 below.

 I have a relativley complex ecosystem app with a couple of hundred imports and a variable number of exports. So, your experince may be different

Because I found the transition into MEF Preview 6 (from 4) painful, here are some suggestions:

  1. Have a working at least slightly tested system before converting
  2. Manually check, double check every Import attribute that they do not import into an IEnumerable. Change these to ImportMany
  3. Manually check, double check every ImportingConstructor to ensure that every IEnumerable parameter is prefaced with an ImportMany attribute
  4. In Preview 6 ONLY If you think you've got a stable composition error, modify this code in the CatalogExportProvider (assuming you are using it) to allow a break point. Since it was compiled in Debug mode, it should have been available for breakpoints, but wasn't on my system and I had little system in working out that problem. This appears around line 559.
                catch (ChangeRejectedException exception)
                {
                    // We should perhaps add non-debug tracing of these errors to help diagosis 
                    // composition issues related to parts being rejected.
                    Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Part {0} was rejected because of the following issue:", newPart));
                    Debug.WriteLine(exception.Message);
                }
Note that it doesn't rethrow. I believe the team is beyond "perhaps" in that comment. And don't anyone dare bash the
team for this particular code as they are giving us very early bits and we are choosign to work on the bleeding edge.
I just added a Console.Writeline, ensured the recompiled version of System.ComponentModel.Composition was up to

date in each of my projects and was able to catch the specifc rejection message.

I anticipate much more help in future versionsi in solving errors masked by stable composition, and it is possible that 
I could have solved this through the Composition Diagnostics, which was just not the route I took.
If someone on the team wants to walk through an easier debugging approach to a problem like this, you won't hurt
any feelings here. This is just an attempt to record what I found to be a rather painful deubbing round to save someone
else time. If there's a way to save more time, feel free. And it would seem that tracing on these failures would be
valuable, even if you also have other strategies.