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.