home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2005 June (DVD) / DPPRO0605DVD.iso / dotNETSDK / SETUP.EXE / netfxsd1.cab / FL_EmitAssembly_cs________.3643236F_FC70_11D3_A536_0090278A1BB8 < prev    next >
Encoding:
Text File  |  2001-08-21  |  7.4 KB  |  184 lines

  1. /*=====================================================================
  2.   File:      EmitAssembly.cs
  3.  
  4.   Summary:   Demonstrates how to use reflection emit.
  5.  
  6. ---------------------------------------------------------------------
  7.   This file is part of the Microsoft .NET SDK Code Samples.
  8.  
  9.   Copyright (C) Microsoft Corporation.  All rights reserved.
  10.  
  11. This source code is intended only as a supplement to Microsoft
  12. Development Tools and/or on-line documentation.  See these other
  13. materials for detailed information regarding Microsoft code samples.
  14.  
  15. THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  16. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  17. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  18. PARTICULAR PURPOSE.
  19. =====================================================================*/
  20.  
  21.  
  22. using System;
  23. using System.Threading;
  24. using System.Reflection;
  25. using System.Reflection.Emit;
  26.  
  27. public class App {
  28.    private static void Usage() {
  29.       Console.WriteLine(
  30.          "Usage:\n" +
  31.          "   1\tCreate & test a dynamic type\n" +
  32.          "   2\tCreate & Save a type (use TestEmittedAssembly.exe to test)\n" +
  33.          "   3\tCreate 2 dynamic assemblies & test them");
  34.    }
  35.  
  36.  
  37.    public static void Main(String[] args) {
  38.       if (args.Length == 0 || !Char.IsDigit(args[0].ToCharArray()[0])) {
  39.          Usage();
  40.          return;
  41.       }
  42.  
  43.       AssemblyBuilder assembly;
  44.  
  45.       switch (Int32.Parse(args[0])) {
  46.          case 1:
  47.          // Create the "HelloWorld" class
  48.          Type helloWorldClass = CreateCallee(Thread.GetDomain(), AssemblyBuilderAccess.Run);         
  49.  
  50.          // Create an instance of the "HelloWorld" class.
  51.          Object helloWorld = Activator.CreateInstance(helloWorldClass, new Object[] { "HelloWorld" });
  52.  
  53.          // Invoke the "GetGreeting" method of the "HelloWorld" class.
  54.          Object obj = helloWorldClass.InvokeMember("GetGreeting", BindingFlags.InvokeMethod, null, helloWorld, null);
  55.          Console.WriteLine("HelloWorld.GetGreeting returned: \"" + obj + "\"");
  56.          break;
  57.  
  58.       case 2:
  59.          assembly = (AssemblyBuilder) CreateCallee(Thread.GetDomain(), AssemblyBuilderAccess.Save).Assembly;
  60.          assembly.Save("EmittedAssembly.dll");
  61.          break;
  62.  
  63.       case 3:         
  64.          Type calleeClass = CreateCallee(Thread.GetDomain(), AssemblyBuilderAccess.Run);
  65.          Type mainClass = CreateCaller(Thread.GetDomain(), AssemblyBuilderAccess.Run, calleeClass);
  66.  
  67.          Object o = Activator.CreateInstance(mainClass);
  68.          mainClass.GetMethod("main").Invoke(o, new Object[0]);
  69.          break;
  70.  
  71.       default:
  72.          Usage();
  73.          break;
  74.       }
  75.    }
  76.  
  77.    // Create the callee transient dynamic assembly.
  78.    private static Type CreateCallee(AppDomain appDomain, AssemblyBuilderAccess access) {
  79.       // Create a simple name for the callee assembly.
  80.       AssemblyName assemblyName = new AssemblyName();
  81.       assemblyName.Name = "EmittedAssembly";
  82.  
  83.       // Create the callee dynamic assembly.
  84.       AssemblyBuilder assembly = appDomain.DefineDynamicAssembly(assemblyName, access);
  85.  
  86.       // Create a dynamic module named "CalleeModule" in the callee assembly.
  87.       ModuleBuilder module;
  88.       if (access == AssemblyBuilderAccess.Run) {
  89.          module = assembly.DefineDynamicModule("EmittedModule");
  90.       } else {
  91.          module = assembly.DefineDynamicModule("EmittedModule", "EmittedModule.mod");
  92.       }
  93.  
  94.       // Define a public class named "HelloWorld" in the assembly.
  95.       TypeBuilder helloWorldClass = module.DefineType("HelloWorld", TypeAttributes.Public);
  96.  
  97.       // Define a private String field named "Greeting" in the type.
  98.       FieldBuilder greetingField = helloWorldClass.DefineField("Greeting", typeof(String), FieldAttributes.Private);
  99.  
  100.       // Create the constructor.
  101.       Type[] constructorArgs = { typeof(String) };
  102.       ConstructorBuilder constructor = helloWorldClass.DefineConstructor(
  103.          MethodAttributes.Public, CallingConventions.Standard, constructorArgs);
  104.  
  105.       // Generate IL for the method. The constructor calls its superclass
  106.       // constructor. The constructor stores its argument in the private field.
  107.       ILGenerator constructorIL = constructor.GetILGenerator();
  108.       constructorIL.Emit(OpCodes.Ldarg_0);
  109.       ConstructorInfo superConstructor = typeof(Object).GetConstructor(new Type[0]);
  110.       constructorIL.Emit(OpCodes.Call, superConstructor);
  111.       constructorIL.Emit(OpCodes.Ldarg_0);
  112.       constructorIL.Emit(OpCodes.Ldarg_1);
  113.       constructorIL.Emit(OpCodes.Stfld, greetingField);
  114.       constructorIL.Emit(OpCodes.Ret);
  115.  
  116.       // Create the GetGreeting method.
  117.       MethodBuilder getGreetingMethod = helloWorldClass.DefineMethod("GetGreeting", 
  118.          MethodAttributes.Public, typeof(String), null);
  119.  
  120.       // Generate IL for GetGreeting.
  121.       ILGenerator methodIL = getGreetingMethod.GetILGenerator();
  122.       methodIL.Emit(OpCodes.Ldarg_0);
  123.       methodIL.Emit(OpCodes.Ldfld, greetingField);
  124.       methodIL.Emit(OpCodes.Ret);
  125.  
  126.       // Bake the class HelloWorld.
  127.       return(helloWorldClass.CreateType());
  128.    }
  129.  
  130.    // Create the caller transient dynamic assembly.
  131.    private static Type CreateCaller(AppDomain appDomain, AssemblyBuilderAccess access, Type helloWorldClass) {
  132.       // Create a simple name for the caller assembly.
  133.       AssemblyName assemblyName = new AssemblyName();
  134.       assemblyName.Name = "CallingAssembly";
  135.  
  136.       // Create the caller dynamic assembly.
  137.       AssemblyBuilder assembly = appDomain.DefineDynamicAssembly(assemblyName, access);
  138.  
  139.       // Create a dynamic module named "CallerModule" in the caller assembly.
  140.       ModuleBuilder module;
  141.       if (access == AssemblyBuilderAccess.Run) {
  142.          module = assembly.DefineDynamicModule("EmittedCallerModule");
  143.       } else {
  144.          module = assembly.DefineDynamicModule("EmittedCallerModule", "EmittedCallerModule.exe");
  145.       }
  146.  
  147.       // Define a public class named MainClass.
  148.       TypeBuilder mainClass = module.DefineType("MainClass", TypeAttributes.Public);
  149.  
  150.       // Create the method with name "main".
  151.       MethodAttributes methodAttributes = (MethodAttributes.Static | MethodAttributes.Public);
  152.       MethodBuilder mainMethod = mainClass.DefineMethod("main", methodAttributes, null, null);
  153.  
  154.       // Generate IL for the method.
  155.       ILGenerator mainIL = mainMethod.GetILGenerator();
  156.  
  157.       // Define the greeting string constant and emit it.
  158.       mainIL.Emit(OpCodes.Ldstr, "HelloWorld (test 3)");
  159.  
  160.       // Use the provided "HelloWorld" class
  161.       // Find the constructor for the "HelloWorld" class.
  162.       Type[] constructorArgs = { typeof(String) };
  163.       ConstructorInfo constructor = helloWorldClass.GetConstructor(constructorArgs);
  164.  
  165.       // Instantiate the "HelloWorld" class.
  166.       mainIL.Emit(OpCodes.Newobj, constructor);
  167.  
  168.       // Find the "GetGreeting" method of the "HelloWorld" class.
  169.       MethodInfo getGreetingMethod = helloWorldClass.GetMethod("GetGreeting");
  170.  
  171.       // Call the "GetGreeting" method to obtain the greeting.
  172.       mainIL.Emit(OpCodes.Call, getGreetingMethod);
  173.  
  174.       // Write the greeting  to the console.
  175.       MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) });
  176.       mainIL.Emit(OpCodes.Call, writeLineMethod);
  177.       mainIL.Emit(OpCodes.Ret);
  178.  
  179.       // Bake the class. You can now create instances of this class if you needed to.
  180.       return(mainClass.CreateType());
  181.    }
  182. }
  183.  
  184.