[code]创建DynamicAssembly

AssemblyName aName = new AssemblyName("DynamicAssemblyExample");
           
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
                   
aName,
                   
AssemblyBuilderAccess.RunAndSave);

           
// For a single-module assembly, the module name is usually
            // the assembly name plus an extension.
            ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");

           
TypeBuilder tb = mb.DefineType(
                "MyDynamicType"
,
                
TypeAttributes.Public);

           
// Add a private field of type int (Int32).
            FieldBuilder fbNumber = tb.DefineField(
                "m_number"
,
               
typeof(int),
               
FieldAttributes.Private);

           
// Define a constructor that takes an integer argument and
            // stores it in the private field.
            Type[] parameterTypes = { typeof(int) };
           
ConstructorBuilder ctor1 = tb.DefineConstructor(
               
MethodAttributes.Public,
               
CallingConventions.Standard,
               
parameterTypes);

           
ILGenerator ctor1IL = ctor1.GetILGenerator();
           
// For a constructor, argument zero is a reference to the new
            // instance. Push it on the stack before calling the base
            // class constructor. Specify the default constructor of the
            // base class (System.Object) by passing an empty array of
            // types (Type.EmptyTypes) to GetConstructor.
            ctor1IL.Emit(OpCodes.Ldarg_0);
           
ctor1IL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
           
// Push the instance on the stack before pushing the argument
            // that is to be assigned to the private field m_number.
            ctor1IL.Emit(OpCodes.Ldarg_0);
           
ctor1IL.Emit(OpCodes.Ldarg_1);
           
ctor1IL.Emit(OpCodes.Stfld, fbNumber);
           
ctor1IL.Emit(OpCodes.Ret);

           
// Define a default constructor that supplies a default value
            // for the private field. For parameter types, pass the empty
            // array of types or pass null.
            ConstructorBuilder ctor0 = tb.DefineConstructor(
               
MethodAttributes.Public,
               
CallingConventions.Standard,
               
Type.EmptyTypes);

           
ILGenerator ctor0IL = ctor0.GetILGenerator();
           
// For a constructor, argument zero is a reference to the new
            // instance. Push it on the stack before pushing the default
            // value on the stack, then call constructor ctor1.
            ctor0IL.Emit(OpCodes.Ldarg_0);
           
ctor0IL.Emit(OpCodes.Ldc_I4_S, 42);
           
ctor0IL.Emit(OpCodes.Call, ctor1);
           
ctor0IL.Emit(OpCodes.Ret);

           
// Define a property named Number that gets and sets the private
            // field.
            //
            // The last argument of DefineProperty is null, because the
            // property has no parameters. (If you don't specify null, you must
            // specify an array of Type objects. For a parameterless property,
            // use the built-in array with no elements: Type.EmptyTypes)
            PropertyBuilder pbNumber = tb.DefineProperty(
                "Number"
,
               
PropertyAttributes.HasDefault,
               
typeof(int),
               
null);

           
// The property "set" and property "get" methods require a special
            // set of attributes.
            MethodAttributes getSetAttr = MethodAttributes.Public |
               
MethodAttributes.SpecialName | MethodAttributes.HideBySig;

           
// Define the "get" accessor method for Number. The method returns
            // an integer and has no arguments. (Note that null could be
            // used instead of Types.EmptyTypes)
            MethodBuilder mbNumberGetAccessor = tb.DefineMethod(
                "get_Number"
,
               
getSetAttr,
               
typeof(int),
               
Type.EmptyTypes);

           
ILGenerator numberGetIL = mbNumberGetAccessor.GetILGenerator();
           
// For an instance property, argument zero is the instance. Load the
            // instance, then load the private field and return, leaving the
            // field value on the stack.
            numberGetIL.Emit(OpCodes.Ldarg_0);
           
numberGetIL.Emit(OpCodes.Ldfld, fbNumber);
           
numberGetIL.Emit(OpCodes.Ret);

           
// Define the "set" accessor method for Number, which has no return
            // type and takes one argument of type int (Int32).
            MethodBuilder mbNumberSetAccessor = tb.DefineMethod(
                "set_Number"
,
               
getSetAttr,
               
null,
               
new Type[] { typeof(int) });

           
ILGenerator numberSetIL = mbNumberSetAccessor.GetILGenerator();
           
// Load the instance and then the numeric argument, then store the
            // argument in the field.
            numberSetIL.Emit(OpCodes.Ldarg_0);
           
numberSetIL.Emit(OpCodes.Ldarg_1);
           
numberSetIL.Emit(OpCodes.Stfld, fbNumber);
           
numberSetIL.Emit(OpCodes.Ret);

           
// Last, map the "get" and "set" accessor methods to the
            // PropertyBuilder. The property is now complete.
            pbNumber.SetGetMethod(mbNumberGetAccessor);
           
pbNumber.SetSetMethod(mbNumberSetAccessor);

           
// Define a method that accepts an integer argument and returns
            // the product of that integer and the private field m_number. This
            // time, the array of parameter types is created on the fly.
            MethodBuilder meth = tb.DefineMethod(
                "MyMethod"
,
               
MethodAttributes.Public,
               
typeof(int),
               
new Type[] { typeof(int) });

           
ILGenerator methIL = meth.GetILGenerator();
           
// To retrieve the private instance field, load the instance it
            // belongs to (argument zero). After loading the field, load the
            // argument one and then multiply. Return from the method with
            // the return value (the product of the two numbers) on the
            // execution stack.
            methIL.Emit(OpCodes.Ldarg_0);
           
methIL.Emit(OpCodes.Ldfld, fbNumber);
           
methIL.Emit(OpCodes.Ldarg_1);
           
methIL.Emit(OpCodes.Mul);
           
methIL.Emit(OpCodes.Ret);

           
// Finish the type.
            Type t = tb.CreateType();

           
// The following line saves the single-module assembly. This
            // requires AssemblyBuilderAccess to include Save. You can now
            // type "ildasm MyDynamicAsm.dll" at the command prompt, and
            // examine the assembly. You can also write a program that has
            // a reference to the assembly, and use the MyDynamicType type.
            //
            ab.Save(aName.Name + ".dll");

           
// Because AssemblyBuilderAccess includes Run, the code can be
            // executed immediately. Start by getting reflection objects for
            // the method and the property.
            MethodInfo mi = t.GetMethod("MyMethod");
           
PropertyInfo pi = t.GetProperty("Number");

           
// Create an instance of MyDynamicType using the default
            // constructor.
            object o1 = Activator.CreateInstance(t);

           
// Display the value of the property, then change it to 127 and
            // display it again. Use null to indicate that the property
            // has no index.
            Console.WriteLine("o1.Number: {0}", pi.GetValue(o1, null));
           
pi.SetValue(o1, 127, null);
           
Console.WriteLine("o1.Number: {0}", pi.GetValue(o1, null));

           
// Call MyMethod, passing 22, and display the return value, 22
            // times 127. Arguments must be passed as an array, even when
            // there is only one.
            object[] arguments = { 22 };
           
Console.WriteLine("o1.MyMethod(22): {0}",
               
mi.Invoke(o1, arguments));

           
// Create an instance of MyDynamicType using the constructor
            // that specifies m_Number. The constructor is identified by
            // matching the types in the argument array. In this case,
            // the argument array is created on the fly. Display the
            // property value.
            object o2 = Activator.CreateInstance(t,
               
new object[] { 5280 });
           
Console.WriteLine("o2.Number: {0}", pi.GetValue(o2, null));
用完要unload或者只创建一次。否则可能导致high memory
posted @ 2008-07-20 23:14  new 维生素C.net()  阅读(576)  评论(0编辑  收藏  举报