Debugging MEF

Debugging problems in the Managed Extensibility Framework (MEF) can be difficult, because the potential issues are different from those in a standard app. This topic presents tips for diagnosing problems that are specific to MEF, and suggests some possible causes for those problems.

The first step in solving a MEF problem is to localize the problem to the MEF portion of the app. The following table lists problems that are specific to MEF.

Problem

Possible causes

An ImportCardinalityMismatchException exception is thrown during composition.

An import could not be filled with a matching export because of a missing or rejected part.

-or-

An import that expected a single export found more than one match.

A collection that has the ImportManyAttribute attribute is missing expected contents.

Expected parts were missing or rejected.

An import that has the DefaultValueAttribute attribute set to true is unexpectedly not filled.

An expected match was missing or rejected.

MEF is designed to robustly adapt to varied configurations. By default, it ignores parts that have missing required dependencies. However, when you're debugging your app, this robustness may make it harder to pinpoint the cause of a problem. You can take these steps to track down problems more easily:

  • Configure the Visual Studio debugger to break when exceptions are thrown.

  • Configure your CompositionContainer object to disable rejection.

In general, if an app throws an exception, the Visual Studio debugger will break execution only if that exception is not subsequently handled. However, you might find it helpful to stop and debug your MEF app immediately when an exception is thrown, because your app may handle exceptions in some way and not surface them to the debugger. To configure the Visual Studio debugger to break when exceptions are thrown, on the menu bar, choose Debug, Exceptions. Make sure that the Thrown box is selected for all the exceptions you would like to set the debugger to break on. (For MEF, these are the exceptions under System.ComponentModel.Composition. See How to: Break When an Exception is Thrown for more information.) These exceptions will now appear in the debugger, even if your app handles them.

By default, MEF uses a process called rejection to determine which parts have all the dependencies they require for instantiation. The composition engine checks whether the addition of the new parts would cause composition to fail. If they may cause failure, those parts are hidden from the container, but an exception is not raised. This behavior results in an app that is more stable in the face of varied deployment configurations, but may make debugging more difficult. To turn off rejection and make sure that MEF raises an exception whenever a part would be rejected, pass the DisableSilentRejection value to your CompositionContainer or ExportProvider object. The following code demonstrates this:

var catalog = new DirectoryCatalog("Extensions");
var container = new CompositionContainer(catalog, CompositionOptions.DisableSilentRejection);

MEF failures are often cascading — that is, a failure to compose one part leads to a failure to compose a second part, and so on, until the observed point of failure is lost in a long list of exceptions. To help diagnose problems of this nature, the CompositionException exception provides the RootCauses property. You can examine this property in the debugger to find the exception that is the root cause of each error in composition.

Starting with the .NET Framework 4.5, MEF supports tracing. Composition failures and exceptions are written to the IntelliTrace window when running in Debug mode in Visual Studio. Examining these results can help diagnose composition failures. See Debug Your App by Recording Code Execution with IntelliTrace for more information on IntelliTrace.

To determine which parts are available to the catalog, you can either examine the Parts property of the catalog in the debugger, or iterate through that property in your code.

If parts you were expecting to see are not present, those parts were either not discovered or were rejected.

If you can see a part, but it doesn't match the expected import, some type of mismatch has occurred. For more information, see the next section.

For an export to match a particular import, the following conditions must be met. If an expected match does not occur, but you have confirmed that the export is present in the catalog, carefully check these conditions. These conditions also apply when you manually construct a contract to match a particular export. For more information, see the ExportProvider.GetExports method.

Property

Conditions for matching

Contract name

Must match exactly, and is case-sensitive. In the case of contract names that are inferred from types (for example, when the ExportAttribute attribute is applied with no parameters), the only possible match is another name that is inferred from the same type.

Contract type

Must match exactly. Polymorphic matching is not supported. Contract types must match even if matching contract names are supplied.

Required metadata

All metadata required by the import through the properties of its metadata view must be provided by the export by using an ExportMetadataAttribute attribute or a custom metadata attribute. Both metadata keys (the names of the properties in the metadata view) and the types of the metadata values must match.

Creation policy

Export and import must not specify different creation policies. For more information, see the CreationPolicy enumeration.

If a part does not appear in the catalog or when using the Composition Analysis Tool (Mefx), that part is not being discovered by the catalog. Here are a few possible reasons for this failure:

  • The part is an abstract type. Abstract types cannot be used as parts. Either make the type non-abstract, or create a non-abstract subtype.

  • The ImportingConstructorAttribute attribute is missing. A part that has multiple constructors or only constructors that accept parameters must specify a constructor for MEF to use with the ImportingConstructorAttribute attribute.

  • The part has the PartNotDiscoverableAttribute attribute. This attribute prevents a part from being discovered.

  • The part is an open generic type. MEF does not support open generic types. Either use a closed subclass of the type, or export individual properties.

Additional failures can occur when you use a DirectoryCatalog object:

  • The part is in an .exe file. The default DirectoryCatalog reads only from .dll files. You can use a DirectoryCatalog object to read from other files by creating it with the appropriate search pattern.

  • The part's assembly has a missing reference. The assemblies you use must be able to load their references from the search path, usually either from their own directory or from the global assembly cache.

  • The part's assembly targets a different CPU type. MEF will not load assemblies that target the wrong CPU type.

Was this page helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft