Criando um assembly em tempo de execução
Vou explicar os passos básicos de como criar um pequeno assembly em tempo de execução, usando Reflection. Usando esses recursos seria possível criar um compilador para IL.
Os assemblies são feitos de: Assembly Metadata, Type Metadata, Code (IL) e Resources
- O Assembly Metadata define propriedades como Nome e Versão do assembly
- Type Metadata define todas as descrições de um tipo, como métodos, propriedades, nome de classe, etc
- Code(IL) é o próprio código
- Resources são imagens, strings, arquivos, etc
Cada assembly deve conter pelo menos um Modulo. Os módulos são uma espécie de caixa que guarda as informações sobre os Tipos.
Então vamos seguir a seguinte ordem, criamos um assembly, um modulo e um tipo, e já teremos o básico.
//namespaces necessarios
using System.Reflection;
using System.Reflection.Emit;
//Criamos um AssemblyName
AssemblyName AsyNome = new AssemblyName("MeuAssembly");
//Então definimos um novo assembly no atual AppDomain, não é possível criar um assembly a partir do próprio construtor
AssemblyBuilder AsyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(AsyNome, AssemblyBuilderAccess.RunAndSave);
//AssemblyBuilderAccess.RunAndSave quer dizer que podemos tanto executar esse assembly, quanto salva-lo
//Criamos o modulo a partir do assembly
ModuleBuilder ModBuilder = AsyBuilder.DefineDynamicModule("MeuModulo", "modulo.dll");
//E um tipo a partir do modulo. Este tipo é publico e serializável, você pode atribuir várias propriedades com o operador |
TypeBuilder TipoBuilder = ModBuilder.DefineType("Meutipo", TypeAttributes.Public | TypeAttributes.Serializable);
//Agora podemos definir os membros do tipo, como construtores, métodos, propriedades, etc
//Vamos criar um campo
FieldBuilder CampoBuilder = TipoBuilder.DefineField("Campo", typeof(int), FieldAttributes.Public);
//Podemos tambem salvar o assembly para uso posterior
AsyBuilder.Save("modulo.dll");
Neste exemplo foi usado somente o FieldBuilder, mas você pode criar qualquer outro membro usando os: ConstructorBuilder para construtor, EnumBuilder para enum, EventBuilder para eventos, etc
Você pode usar esse recurso para criar um software que aceite plug-ins por exemplo.