This chapter is from msdn.
I. general debugging methods
Debugging problems in managed extensibility framework (MEF) can be very difficult because the potential problems are different from those in standard applications. This topic provides MEF-specific problem diagnosis techniques and provides possible causes for these problems.
MEF problems found
The first step to solve the MEF problem is to locate the problem in the MEF section of the application. The following table lists MEF-specific issues.
Problem |
Possible causes |
Importcardinalitymismatchexception is thrown during the combination. |
Due to missing or rejected parts, a matching export fill cannot be used for import. -Or- Multiple matching items are expected to be found for a single exported import. |
The set with the importmanyattribute feature lacks the expected content. |
The expected parts are missing or rejected. |
Set the defavaluvalueattribute featureTrue. |
Expected matches are missing or rejected. |
Handle exceptions and disablesilentrejection
MEF is designed to reliably adapt to various configurations. By default, it ignores parts with missing required dependencies. However, when you debug an application, this reliability makes it more difficult to find the cause of the problem. You can follow these steps to track problems more easily:
When an exception is thrown, configure the Visual Studio debugger to interrupt.
Configure your compositioncontainer object to disable denial.
Generally, if an exception occurs in an application, the Visual Studio debugger interrupts execution only when the exception does not pass post-processing. However, you may find it helpful to stop and debug your MEF application immediately when an exception is thrown because your application will handle the exception in some ways, it is not reflected in the debugger. To configure the Visual Studio debugger when an exception is thrown, on the menu bar, select"Debugging","Exception". Make sure all exceptions are selected"Cause"Box, you want to set the debugger to interrupt when these exceptions occur. (For MEF, these areSystem. componentmodel. Composition. These exceptions are displayed in the debugger even if your application processes them.
By default, MEF uses a process called denial to determine which parts will be called for instantiation for relevance. The composition engine checks whether the addition of new parts causes the combination to fail. If they may cause a failure, hide those parts from the container without causing an exception. This behavior can make the application more stable, but may make debugging more difficult. If you want to disable denial whenever a part is rejected and make sure that MEF raises an exception, pass the disablesilentrejection value setting to the compositioncontainer or exportprovider object. The following code describes this:
Code segment
var catalog = new DirectoryCatalog("Extensions");var container = new CompositionContainer(catalog, CompositionOptions.DisableSilentRejection);
The MEF failure is usually cascade, that is, if a component fails to be combined, the second component fails to be combined, and so on, until the observed failure point is lost in the abnormal long list. To help diagnose this attribute, the rootcauses attribute is provided for compositionexception. You can check this attribute in the debugger to find the exception that is the root cause of each error in the combination.
Tracking
Starting from. NET Framework 4.5, MEF supports tracking. When running, in Visual Studio debugging mode, combined faults and exceptions will be written"Intelliitrace"Window. Checking these results helps diagnose a combination failure. UsageIntelliitrace.
Check available parts
To determine which parts can be used for a directory, you can check the parts attribute of the directory in the debugger and access this attribute cyclically in the code.
If the part you want to see does not exist, the part is not found or rejected.
If you can see a part, but it does not match the import you want it to fill in, it indicates a type of mismatch.
Export/import Mismatch
To match the export with a specific import, all of the following conditions must be met. If no expected match exists, but you have confirmed that the export exists in the directory, check these conditions carefully. These conditions also apply when you manually construct a contract to match a specific export.
Attribute |
Matching condition |
Protocol name |
Must be fully matched and case sensitive. If the protocol name is inferred from the type (for example, when the exportattribute feature is applied without any parameters ), the only possible match is another name inferred from the same type. |
Protocol Type |
Must be exactly matched. Polymorphism matching is not supported. The protocol type must match even if a matching protocol name is provided. |
Required metadata |
All metadata required by the attributes imported through the metadata view must be provided by the export through the exportmetadataattribute feature or custom metadata feature. The metadata key (the name of the attribute in the metadata view) and the type of the metadata value must match. |
Create Policy |
You cannot specify different creation policies for export and import. For more information, see creationpolicy. |
Problems Found
If the part is not displayed in the directory or is not displayed when you use the Combined Analysis Tool (mefx), the part is not found in the directory. Here are some possible causes of this fault:
This part is of the abstract type. Abstract types cannot be used as parts. Make the type non-abstract, or create a non-Abstract subtype.
The importingconstructorattribute feature is missing. For parts with multiple constructors or constructors that only accept parameters, you must specify a constructor so that MEF can use the importingconstructorattribute feature.
This part has the partnotdiscoverableattribute feature. This feature prevents component discovery.
This component is an open generic type. MEF does not support open generics. Use a closed subclass of the type or export a single attribute.
Other faults may occur when you use the directorycatalog object:
This part is located in the. exe file. By default, directorycatalog is read only from DLL files. You can use the directorycatalog object to read from other files by using the corresponding search mode.
The Assembly of the component has a missing reference. The used assembly cannot load its reference from the search path (usually from their own directory or from the Global Assembly Cache.
The assembly of this component is intended for other CPU types. MEF does not parse the incorrect CPU-type assembly.
2. Combined analysis tools (mefx)
A Combined Analysis Tool (mefx) is a command-line application that analyzes the Library (. dll) and application (.exe) files that contain managed extensibility framework (MEF) components. The main purpose of mefx is to provide developers with a way to diagnose combined faults in MEF applications without adding tedious trace code to the application itself. It can also be used to help you understand components in libraries provided by third parties. This topic describes how to use mefx and provides syntax reference.
This topic contains the following sections.
Get mefx
You can obtain mefx on the managed extensibility framework of codeplex. Download and decompress the tool.
Basic syntax
Mefx is called from the command line in the following format:
Mefx [files and directories] [action] [Options]
The first group of parameters specifies the files and directories from which parts are loaded for analysis. Use/file: to specify a file, use/directory: to specify a directory. Multiple files or directories can be specified, as shown in the following example:
Mefx/file: myaddin. dll/directory: Program \ addins [Action...]
Description |
Each. dll or. EXE should be loaded only once. If a file is loaded multiple times, the tool may return incorrect information. |
After the file and directory list, you must specify the command and any options for the command.
List available parts
Use the/parts operation to list all parts declared in the loaded file. The result is a simple part name list.
Mefx/file: myaddin. dll/Parts
Myaddin. addin
Myaddin. memberpart
To obtain more information about the part, use the/verbose option. This will output more information about all available parts. To obtain more information about a single part, use/type instead of/parts.
Mefx/file: myaddin. dll/type: myaddin. addin/verbose
[Part] myaddin. memberpart from: assemblycatalog (Assembly = "myaddin, version = 1.0.0.0, culture = neutral, publickeytoken = NULL ")
[Export] myaddin. memberpart (contractname = "myaddin. memberpart ")
List Import and Export
The/imports and/exports operations list all imported parts and all exported parts respectively. You can also use/importers or/exporters to list imported or exported parts of a specific type.
Mefx/file: myaddin. dll/importers: myaddin. memberpart
Myaddin. addin
You can also apply the/verbose option for these operations.
Find rejected parts
After the available parts are loaded, mefx uses the MEF combination engine to combine them. Parts that cannot be combined are called rejected parts ". To list all rejected parts, use/rejected.
You can use the/verbose option in combination with the/rejected Operation to output detailed information about the rejected parts. In the following example, classlibrary1 dll contains the addin part, which is imported into the memberpart and chainone part. Chainone imports chaintwo, but chaintwo does not exist. This means that chainone is rejected, which will cause addin to be rejected.
Mefx/file: classlibrary1.dll/rejected/verbose
The complete output of the preceding command is shown below:
[Part] classlibrary1.addin from: assemblycatalog (Assembly = "classlibrary1, version = 1.0.0.0, culture = neutral, publickeytoken = NULL ")
[Export] classlibrary1.addin (contractname = "classlibrary1.addin ")
[Import] classlibrary1.addin. memberpart (contractname = "classlibrary1.memberpart ")
[Satisfiedby] classlibrary1.memberpart (contractname = "classlibrary1.memberpart") from: classlibrary1.memberpart from: assemblycatalog (Assembly = "classlibrar
Y1, version = 1.0.0.0, culture = neutral, publickeytoken = NULL ")
[Import] classlibrary1.addin. Chain (contractname = "classlibrary1.chainone ")
[Exception] system. componentmodel. composition. importcardinalitymismatchexception: no valid exports were found that match the constraint '(exportdefinition. contractname = "classlibrary1.chainone") andalso (exportdefinition. metadata. containskey ("exporttypeidentity") andalso "classlibrary1.chainone ". equals (exportdefinition. metadata. get_item ("exporttypeidentity") ', invalid exports may have been rejected.
At system. componentmodel. Composition. Hosting. exportprovider. getexports (importdefinition definition, atomiccomposition)
At Microsoft. componentmodel. Composition. Diagnostics. compositioninfo. analyzeimportdefinition (exportprovider host, ienumerable '1 availableparts, importdefinition ID)
[Unsuitable] classlibrary1.chainone (contractname = "classlibrary1.chainone ")
From: classlibrary1.chainone from: assemblycatalog (Assembly = "classlibrary1, version = 1.0.0.0, culture = neutral, publickeytoken = NULL ")
[Because] partdefinitionisrejected, the part providing the export is rejected because of other issues.
[Part] classlibrary1.chainone from: assemblycatalog (Assembly = "classlibrary1, version = 1.0.0.0, culture = neutral, publickeytoken = NULL ")
[Primary rejection]
[Export] classlibrary1.chainone (contractname = "classlibrary1.chainone ")
[Import] classlibrary1.chainone. Chain (contractname = "classlibrary1.chaintwo ")
[Exception] system. componentmodel. composition. importcardinalitymismatchexception: no valid exports were found that match the constraint '(exportdefinition. contractname = "classlibrary1.chaintwo") andalso (exportdefinition. metadata. containskey ("exporttypeidentity") andalso "classlibrary1.chaintwo ". equals (exportdefinition. metadata. get_item ("exporttypeidentity") ', invalid exports may have been rejected.
At system. componentmodel. Composition. Hosting. exportprovider. getexports (importdefinition definition, atomiccomposition)
At Microsoft. componentmodel. Composition. Diagnostics. compositioninfo. analyzeimportdefinition (exportprovider host, ienumerable '1 availableparts, importdefinition ID)
The information to be followed is included in the [Exception] and [unsuitable] results. [Exception] The result shows the reason why the part is rejected. The [unsuitable] result indicates why a part that matches in other ways cannot be used for filling in the import. In this example, the part itself is denied due to missing import.
Analyze the main causes
If some parts are linked to a long dependency chain, the entire chain may be rejected when the parts involved are close to the bottom. It may be very difficult to diagnose these problems, because the root cause of the fault is not always very obvious. To help diagnose problems, you can use the/causes operation to find the root cause of all cascading rejection.
The previous example uses the/causes operation to list only the information of chainone, which is not filled with the import is the root cause of the rejection of addin. The/causes operation can be used in the normal and/verbose options.
Description |
In most cases, mefx can diagnose the root cause of a cascade fault. However, mefx will not be able to diagnose the cause of situations where components are added to the container programmatically, when a hierarchical container is involved, or when a custom exportprovider implementation is involved. In general, avoid the situations described above as much as possible, because faults are usually difficult to diagnose. |
Whitelist
The/whitelist option allows you to specify a text file that lists parts that should be rejected. Then, an unexpected rejection is marked. This may be useful when you analyze incomplete libraries or child libraries that lack some dependencies. The/whitelist option can be applied to/rejected or/causes operations.
Consider a file named test.txt that contains the text "classlibrary1.chainone ". If you run the/rejected Operation with the/whitelist option on the preceding example, the following output is generated:
Mefx/file: classlibrary1.dll/rejected/whitelist: test.txt
[Unexpected] classlibrary1.addin
Classlibrary1.chainone