Ferramenta de Análise de Composição (Mefx)Composition Analysis Tool (Mefx)

A Ferramenta de Análise de Composição (Mefx) é um aplicativo de linha de comando que analisa arquivos de biblioteca (.dll) e de aplicativo (.exe) que contêm partes do MEF (Managed Extensibility Framework).The Composition Analysis Tool (Mefx) is a command-line application that analyzes library (.dll) and application (.exe) files containing Managed Extensibility Framework (MEF) parts. A principal finalidade da Mefx é fornecer aos desenvolvedores uma maneira de diagnosticar falhas de composição em seus aplicativos MEF sem a necessidade de adicionar um código de rastreamento inconveniente ao próprio aplicativo.The primary purpose of Mefx is to provide developers a way to diagnose composition failures in their MEF applications without the requirement to add cumbersome tracing code to the application itself. Ele também pode ser útil para ajudar a entender as partes de uma biblioteca fornecida por terceiros.It can also be useful to help understand parts from a library provided by a third party. Este tópico descreve como usar a Mefx e fornece uma referência para sua sintaxe.This topic describes how to use Mefx and provides a reference for its syntax.

Obtendo a MefxGetting Mefx

A Mefx está disponível no GitHub em Managed Extensibility Framework.Mefx is available on GitHub at Managed Extensibility Framework. Basta baixar e descompactar a ferramenta.Simply download and unzip the tool.

Sintaxe básicaBasic Syntax

A Mefx é invocada na linha de comando no seguinte formato:Mefx is invoked from the command line in the following format:

mefx [files and directories] [action] [options]  

O primeiro conjunto de argumentos especifica os arquivos e os diretórios dos quais as partes devem ser carregadas para análise.The first set of arguments specify the files and directories from which to load parts for analysis. Especifique um arquivo com a opção /file: e um diretório com a opção /directory:.Specify a file with the /file: switch, and a directory with the /directory: switch. Você pode especificar vários arquivos ou diretórios, conforme é mostrado no exemplo a seguir:You can specify multiple files or directories, as shown in the following example:

mefx /file:MyAddIn.dll /directory:Program\AddIns [action...]  

Observação

Cada arquivo .dll ou .exe deve ser carregado somente uma vez.Each .dll or .exe should only be loaded one time. Se algum arquivo for carregado várias vezes, a ferramenta poderá retornar informações incorretas.If a file is loaded multiple times, the tool may return incorrect information.

Depois da lista de arquivos e diretórios, você deverá especificar um comando e as opções para esse comando.After the list of files and directories, you must specify a command, and any options for that command.

Listando as partes disponíveisListing Available Parts

Use a ação /parts para listar todas as partes declaradas nos arquivos carregados.Use the /parts action to list all the parts declared in the files loaded. O resultado é uma lista simple de nomes de parte.The result is a simple list of part names.

mefx /file:MyAddIn.dll /parts  
MyAddIn.AddIn  
MyAddIn.MemberPart  

Para obter mais informações sobre as partes, use a opção /verbose.For more information about the parts, use the /verbose option. Isso produzirá mais informações para todas as partes disponíveis.This will output more information for all available parts. Para obter mais informações sobre uma única parte, use a ação /type em vez de /parts.To get more information about a single part, use the /type action 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")  

Listando as importações e exportaçõesListing Imports and Exports

As ações /imports e /exports listarão todas as partes importadas e todas as partes exportadas, respectivamente.The /imports and /exports actions will list all the imported parts and all the exported parts, respectively. Você também pode listar as partes que importam ou exportam um tipo específico usando as ações /importers ou /exporters.You can also list the parts that import or export a particular type by using the /importers or /exporters actions.

mefx /file:MyAddIn.dll /importers:MyAddin.MemberPart  
MyAddin.AddIn  

Você também pode aplicar a opção /verbose a essas ações.You can also apply the /verbose option to these actions.

Localizando as partes rejeitadasFinding Rejected Parts

Depois de carregar as partes disponíveis, a Mefx usa o mecanismo de composição do MEF para compô-las.Once it has loaded the available parts, Mefx uses the MEF composition engine to compose them. As partes que não podem ser compostas com êxito são chamadas de rejeitadas.Parts that cannot be successfully composed are referred to as rejected. Para listar todas as partes rejeitadas, use a ação /rejected.To list all the rejected parts, use the /rejected action.

Você pode usar a opção /verbose com a ação /rejected para imprimir informações detalhadas sobre as partes rejeitadas.You can use the /verbose option with the /rejected action to print detailed information about rejected parts. No exemplo a seguir, a DLL ClassLibrary1 contém a parte AddIn, que importa as partes MemberPart e ChainOne.In the following example, the ClassLibrary1 DLL contains the AddIn part, which imports the MemberPart and ChainOne parts. A ChainOne importa a ChainTwo, mas a ChainTwo não existe.ChainOne imports ChainTwo, but ChainTwo does not exist. Isso significa que a ChainOne foi rejeitada, o que faz com que a AddIn seja rejeitada.This means that ChainOne is rejected, which causes AddIn to be rejected.

mefx /file:ClassLibrary1.dll /rejected /verbose  

O exemplo a seguir mostra a saída completa do comando anterior:The following shows the complete output of the previous command:

[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 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 atomicComposition)  
   at Microsoft.ComponentModel.Composition.Diagnostics.CompositionInfo.AnalyzeImportDefinition(ExportProvider host, IEnumerable`1 availableParts, ImportDefinition id)  

As informações interessantes estão contidas nos resultados de [Exception] e [Unsuitable].The interesting information is contained in the [Exception] and [Unsuitable] results. O resultado de [Exception] fornece informações sobre por que uma parte foi rejeitada.The [Exception] result provides information about why a part was rejected. O resultado [Unsuitable] indica por que uma parte com outro tipo de correspondência não pôde ser usada para preencher uma importação. Nesse caso, porque essa parte foi rejeitada devido à ausência de importações.The [Unsuitable] result indicates why an otherwise-matching part could not be used to fill an import; in this case, because that part was itself rejected for missing imports.

Analisando a causa principalAnalyzing Primary Causes

Se várias partes estiverem vinculadas em uma cadeia longa de dependência, um problema envolvendo uma parte próxima à parte inferior poderá fazer com que a cadeia inteira seja rejeitada.If several parts are linked in a long dependency chain, a problem involving a part near the bottom may cause the entire chain to be rejected. O diagnóstico desses problemas pode ser difícil, pois a causa raiz da falha nem sempre é óbvia.Diagnosing these problems can be difficult because the root cause of the failure is not always obvious. Para ajudar a resolver o problema, você pode usar a ação /causes, que tenta localizar a causa raiz de qualquer rejeição em cascata.To help with the problem, you can use the /causes action, which attempts to find the root cause of any cascading rejection.

O uso da ação /causes no exemplo anterior listaria apenas as informações para ChainOne, cuja importação não preenchida é a causa raiz da rejeição de AddIn.Using the /causes action on the previous example would list only information for ChainOne, whose unfilled import is the root cause of the rejection of AddIn. A ação /causes pode ser usada nas opções normal e /verbose.The /causes action can be used in both normal and /verbose options.

Observação

Na maioria dos casos, a Mefx poderá diagnosticar a causa raiz de uma falha em cascata.In most cases, Mefx will be able to diagnose the root cause of a cascading failure. No entanto, nos casos em que as partes são adicionadas de forma programática a um contêiner, nos que envolvem contêineres hierárquicos ou nos que envolvem implementações de ExportProvider personalizadas, a Mefx não pode diagnosticar a causa.However, in cases where parts are added programmatically to a container, cases involving hierarchical containers, or cases involving custom ExportProvider implementations, Mefx will not be able to diagnose the cause. Em geral, esses casos descritos devem ser evitados sempre que possível, pois as falhas geralmente são difíceis de diagnosticar.In general, the previously described cases should be avoided where possible, as failures are generally difficult to diagnose.

Listas de permissõesAllow lists

A opção /whitelist permite que você especifique um arquivo de texto que lista as partes que devem ser rejeitadas.The /whitelist option enables you to specify a text file that lists parts that are expected to be rejected. Assim, as rejeições inesperadas serão sinalizadas.Unexpected rejections will then be flagged. Isso pode ser útil quando você analisa uma biblioteca incompleta ou uma subbiblioteca que não tem algumas dependências.This can be useful when you analyze an incomplete library, or a sublibrary that's missing some dependencies. A opção /whitelist pode ser aplicada às ações /rejected ou /causes.The /whitelist option can be applied to the /rejected or /causes actions.

Considere um arquivo chamado test.txt que contenha o texto "ClassLibrary1.ChainOne".Consider a file named test.txt that contains the text "ClassLibrary1.ChainOne". Se você executar a /rejected ação com a /whitelist opção no exemplo anterior, ela produzirá a seguinte saída:If you run the /rejected action with the /whitelist option on the previous example, it produces the following output:

mefx /file:ClassLibrary1.dll /rejected /whitelist:test.txt  
[Unexpected] ClassLibrary1.AddIn  
ClassLibrary1.ChainOne