Assembly e Managed Module

 

A plataforma .NET têm o seu conjunto de conceitos, estruturas e técnicas. Neste texto eu descrevo sobre dois destes conceitos: Assembly e Managed Module.

 

O texto descreve como estes dois conceitos são utilizados na plataforma .NET para armazenar e distribuir os componentes que compõe os softwares e recursos necessários aos mesmos.

 

Os exemplos de código/projetos citados neste texto foram desenvolvidos e estão disponíveis para as seguintes tecnologias/ferramentas:


- .NET Framework Version: v3.5

- C# Compiler Version : 3.5.21022.8

- C++/CLI Compiler Version : 15.00.21022.08 for 80x86

- ILAsm

- ILDasm

- Visual Studio 2008 Team System

 

 

 

Criando Managed Module

 

A partir do código-fonte do seu aplicativo, as ferramentas de compilação e de geração de arquivos, criam arquivos binários como resultado destes processos. No Microsoft Windows, o formato de arquivo PE/COFF (Portable Executable and Common Object File Format), é o padrão utilizado para os arquivos do tipo EXE e DLL. Este formato é utilizado nas versões 32-bit e 64-bit dos sistemas operacionais da Microsoft. Os compiladores para a plataforma .NET geram arquivos binários no formato de arquivo PE/COFF.

 

Na realidade o formato PE/COFF é uma versão modificada do formato de arquivo COFF (Common Object File Format) do Unix. O PE/COFF foi implementado a partir do Windows NT 3.1. Como o PE/COFF é um formato amplamente reconhecido e utilizado, criar um novo formato de arquivo específico para o .NET não era viável e por isto a plataforma .NET o utiliza mas inclui informações e estruturas que são reconhecidas pelo CLR (Common Language Runtime). Estas estruturas e informações não alteram as estruturas do formato PE/COFF e sim são extensões. Portanto o arquivo ainda é reconhecido pelo sistema operacional como um arquivo PE/COFF válido.

 

Com estas informações podemos agora descrever mais detalhadamente o conceito de ManagedModule.


Managed Module

 

Q: Como são organizados fisicamente os códigos e recursos que utilizo em meus softwares para a plataforma .NET ?

 

A: Os programas escritos para o CLR – Common Language Runtime residem em Managed Modules. Os códigos compilados e os recursos que compõe o software são armazenados em uma estrutura física (arquivo PE/COFF) descrita como Managed Module.  Em um Managed Module é possível armazenar vários tipos de informação além do código CIL (Common Intermediate Language) gerado pelo compilador.

 

Q: Mas o que é um Managed Module afinal?

 

Um arquivo no formato PE/COFF (Portable Executable and Common Object File Format), cujo conteúdo pode ser executado pelo CLR – Common Language Runtime.

 

Q: Sendo o Managed Module a forma como as informações são gravadas em arquivo para que este seja executado, quais tipos de informação um Managed Module pode armazenar?

 

A: Um Managed Module pode ter em seu conteúdo:

 

·        Código (CIL – Common Intermediate Language e native code).

·        Metadata

·        Resources

 

Código: O código gerado pelos compiladores é transformado em CIL (Common Intermediate Language) e armazenado no Managed Module. Um Managed Module também pode armazenar código binário nativo, ou seja, específico para uma arquitetura de processador.

 

Metadata: Armazenam as descrições dos tipos definidos no Managed Module incluindo: nomes, relacionamentos de herança, assinaturas de métodos, informações de dependência, descrições de estruturas internas e assim por diante.

 

Resources: Os resources contêm dados estáticos e somente para leitura como strings, arquivos de imagens e outros aspectos do programa que não são armazenados como código executável.

 

Para demonstrar como é um Managed Module há uma solução de exemplo, que faz parte deste texto, com a seguinte organização:


 

Projetos nas linguagens C++/CLI e C#

·        Solution Folder: AssembliesAndModules

o   Visual Studio Solution: AssembliesAndModules.sln

§  Solution Folder: CPPCLI2008

·        Project: CPPCLI.OpenMind.Example01

·        Project: CSHARP.Test.Application

§  Solution Folder: CS2008

·        Project: CS.OpenMind.Example01

 

 

Os projetos CPPCLI.OpenMind.Example01 e CS.OpenMind.Example01 têm uma classe cada e estas têm dois métodos simples que apenas exibem mensagens de texto. Eles servem apenas para ilustrar o código CIL (Common Intermediate Language) gerado. Um item interessante é o projeto CSHARP.Test.Application que está no solution folder CPPCLI2008. Se você expandir a lista de referências do projeto CSHARP.Test.Application, notará que existe uma referência para o projeto em C++/CLI CPPCLI.OpenMind.Example01 e a classe Program.cs utiliza a classe gerada em C++/CLI. Este exemplo simples demonstra como a plataforma .NET é bem projetada e poderosa.

 

Exemplo do conteúdo de um Managed Module

 

Os dois exemplos abaixo demonstram o CIL (Common Intermediate Language) gerado para os projetos de exemplo escritos nas linguagens C++/CLI e C#. Os projetos estão disponíveis para download nos seguintes links:

 

·        Clique aqui para download da solução com os projetos de exemplo.

 

Projeto CS.OpenMind.Example01

 

 

 

O código abaixo é o CIL (Common Intermediate Language) do Managed ModuleCS.OpenMind.Example01, escrito originalmente na linguagem C#.

 

 

No exemplo abaixo estão trechos do que é gerado cada vez que um arquivo binário para a plataforma .NET é criado. No Managed Module há informações estruturais e o código que você escreveu na linguagem C# compilado para CIL (Common Intermediate Language). Na linha em destaque (na cor amarela) você lê a diretiva .module  CS.OpenMind.Example01.dll que indica o nome deste Managed Module. Você também lê neste trecho (na cor cinza) o nome do Assembly do qual o Managed Module faz parte. Este tipo de Assembly é definido na plataforma .NET como single-module Assembly. 

 

 

Trechos do código em CIL (Common Intermediate Language) para o Managed Module CS.OpenMind.Example01.dll

// Metadata version: v2.0.50727

.assembly extern mscorlib

{

  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..

  .ver 2:0:0:0

}

.assembly CS.OpenMind.Example01

{

… (OUTRAS INFORMAÇÕES DO MANAGED MODULE)

}

.module CS.OpenMind.Example01.dll

// MVID: {D564A821-9F51-4EDD-9634-0E29BBA2FC4A}

.imagebase 0x00400000

.file alignment 0x00001000

.stackreserve 0x00100000

.subsystem 0x0003       // WINDOWS_CUI

.corflags 0x00000001    //  ILONLY

// Image base: 0x00A90000

 

Projeto CPPCLI.OpenMind.Example01

 

 

 

O código abaixo é o CIL (Common Intermediate Language) do Managed ModuleCPPCLI.OpenMind.Example01, escrito originalmente na linguagem C++/CLI.

 

 

 

O que você lê no exemplo abaixo são trechos do que é gerado cada vez que um arquivo binário para a plataforma .NET é criado. No Managed Module há informações estruturais e o código que você escreveu na linguagem C++/CLI compilado para CIL (Common Intermediate Language). Na linha em destaque (na cor amarela) você lê a diretiva .module  CPPCLI.OpenMind.Example01.dll que indica o nome deste Managed Module. Você também lê neste trecho (na cor cinza) o nome do Assembly do qual este Managed Module faz parte. Este tipo de Assembly é definido na plataforma .NET como single-module Assembly. 

 

 

 

Trechos do código em CIL (Common Intermediate Language) para o Managed Module CPPCLI.OpenMind.Example01.dll

// Metadata version: v2.0.50727

.assembly extern mscorlib

{

  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..

  .hash = (EE 68 AE BC CF 3A 00 D9 99 47 67 8A CB B4 86 C1   // .h...:...Gg.....

           0B 52 25 4C )                                     // .R%L

  .ver 2:0:0:0

}

.assembly CPPCLI.OpenMind.Example01

{

  …(OUTRAS INFORMAÇÕES DO MANAGED MODULE)

}

.module CPPCLI.OpenMind.Example01.dll

// MVID: {4D59A8D0-7A89-4517-9D6B-A5DCA9851C22}

.imagebase 0x10000000

.file alignment 0x00000200

.stackreserve 0x00100000

.subsystem 0x0002       // WINDOWS_GUI

.corflags 0x00000003    //  ILONLY 32BITREQUIRED

// Image base: 0x00950000

 

 

Com a definição e o exemplo de um Managed Module vamos conversar agora sobre como distribuir estes binários da plataforma .NET.

 

Assembly

 

Um Assembly é uma coleção de recursos que são construídos para funcionarem juntos. Deste modo proporcionam um conjunto coeso de funcionalidades. Coleções de componentes .NET e outros arquivos são organizados para distribuição em Assemblies.

 

O propósito do Assembly é criar um modelo de distribuição que permita ao CLR (Common Language Runtime), entre outras coisas, identificar quais são os recursos (como DLL´s nativas, assemblies, arquivos de imagens, por exemplo) que compõe a sua unidade de distribuição e, portanto são indispensáveis para o correto funcionamento da aplicação. Um Assembly pode ser descrito como uma metafile. Ele existe conceitualmente e estruturalmente, mas não existe como um arquivo físico (PE/COFF) e não deve ser confundido com um.

 

 

Quando o compilador gera um Managed Module e as informações para o Assembly ao qual o Managed Module pertence, também são geradas as informações de dependência de outros Assemblies . Estas informações de dependência também são representadas na linguagem CIL (Common Intermediate Language).

 

Obtendo informações: Metadados

 

A plataforma .NET têm uma API (Application Programming Interface) que nos permite, tanto via código nativo ou usando uma das linguagens para plataforma .Net, como a C#, obter informações sobre a estrutura interna de um Managed Module e/ou Assembly. Estas informações são recuperadas dos Metadados. A API e o grupo de conceitos e técnicas para ler estas informações são chamados coletivamente de Reflection.

 

No projeto CSHARP.Test.Application existe um método static chamado ShowInfoAboutModulesAndAssemblies que exibe as informações sobre o Managed Module e os Assemblies.

 

Primeiro este método obtêm uma referência para uma instância da classe Module usando a classe Program.

 

Module module = typeof(Program).Module;

 

Em seguida ele utiliza a variável module para exibir o nome do Managed Module em que  a classe Program do CSHARP.Test.Application está definida. Você vai observar que o código utiliza a propriedade Name da classe Module para exibir esta informação.

 

Console.WriteLine("Module Name: {0}{1}", module.Name, Environment.NewLine );

 

A informação apresentada é:

 

Module Name: CSHARP.Test.Applicaton.exe

 

Como você pode observar, o nome do Managed Module é o nome do arquivo PE/COFF.

 

Em seguida, para este mesmo Managed Module, é exibida a informação sobre qual é o AssemblyManaged Module está definido. Para isto eu utilizo a propriedade FullName  da classe Assembly. em que este

 

Console.WriteLine("Assembly FullName {0} {1}:", module.Assembly.FullName.ToString(), Environment.NewLine );

 

 A informação exibida é a seguinte:

 

Assembly FullName:

 CSHARP.Test.Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.

 

Como você pode notar não há nada nas informações sobre o Assembly que indique que é um arquivo físico. Com isto fica mais claro o conceito de Assembly.

 

Para completar o exemplo, os Assemblies que são referenciados pelo CSHARP.Test.Application são listados utilizando o seguinte trecho de código:

 

AssemblyName[] referencedAssemblies = module.Assembly.GetReferencedAssemblies();

 

foreach (AssemblyName assemblyName in referencedAssemblies) {

   Console.WriteLine( "Referenced Assembly FullName: {0} {1}", assemblyName.FullName, Environment.NewLine );

}

 

As informações exibidas são:

 

Referenced Assembly FullName:

mscorlib, Version=2.0.0.0, Culture=neutral, Public KeyToken=b77a5c561934e089

Referenced Assembly FullName:

CPPCLI.OpenMind.Example01, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

 

Mais uma vez podemos observar que o conceito de Assembly representa uma unidade de distribuição e funcionalidades associadas. Neste exemplo, para o AssemblyCSHARP.Test.Application e seu Managed Module CSHARP.Test.Application.exe realizarem as suas tarefas é necessário que os demais Managed Modules e os respectivos Assemblies existam e estejam acessíveis para a aplicação.

 

 

Os conceitos citados aqui estão disponíveis na documentação da plataforma .NET no site: http://msdn.microsoft.com.

 

"Para todas as pessoas que nunca deixam de perguntar: Como isto funciona?"

Para a versão integral deste artigo no formato PDF e XPS vá até este endereço:
http://cid-51f567d444ca91c7.skydrive.live.com/browse.aspx/Samples?view=details

Nesta pasta existem 3 arquivos:

- AssembliesAndModules.zip
- CLR- Fundamentals - Assembly and Module.pdf
- CLR- Fundamentals - Assembly and Module.xps

Que são respectivamente: a solução com os projetos de exemplo, a versão, no formato PDF, completa deste artigo e a versão, no formato XPS, completa deste artigo.