MSIL实用指南-创建对象

时间:2023-06-06 22:17:37

创建对象用Newobj指令,它的操作是创建一个新的对象或值类型,并将对象引用的新实例到计算堆栈上。
格式是
Newobj <构造函数>
实例:

ilGenerator.Emit(OpCodes.Newobj, typeof(Uri).GetConstructor(new Type[] { typeof(string)}));

在调用Newobj指令前,需要加载构造函数所需要的参数。

完整程序如下:

using System;
using System.Reflection;
using System.Reflection.Emit; namespace LX1_ILDemo
{
class Demo15_NewObj
{
static string binaryName = "Demo15_NewObj.exe";
static string namespaceName = "LX1_ILDemo";
static string typeName = "NewObjDemo"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder;
static MethodBuilder mainMethod;
static ILGenerator ilGenerator; static void Emit_ILCode()
{
LocalBuilder localBuilderv1 = ilGenerator.DeclareLocal(typeof(Uri));
ilGenerator.Emit(OpCodes.Ldstr, "http://www.contoso.com/");
ilGenerator.Emit(OpCodes.Newobj, typeof(Uri).GetConstructor(new Type[] { typeof(string)}));
ilGenerator.Emit(OpCodes.Stloc_0);
ilGenerator.Emit(OpCodes.Ldloc_0);
ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }));
} public static void Generate()
{
InitAssembly(); typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName, TypeAttributes.Public); GenerateMain(); Emit_ILCode(); EmitReadKey();
ilGenerator.Emit(OpCodes.Ret); /* 设置assembly入口方法 */
assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication); SaveAssembly();
Console.WriteLine("生成成功");
} static void EmitReadKey()
{
/* 生成 Console.ReadKey(); */
MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
ilGenerator.Emit(OpCodes.Call, readKeyMethod);
ilGenerator.Emit(OpCodes.Pop);
} static void GenerateMain()
{
mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
| MethodAttributes.Static, typeof(void), new Type[] { });
ilGenerator = mainMethod.GetILGenerator();
} static void InitAssembly()
{
AssemblyName assemblyName = new AssemblyName(namespaceName);
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, binaryName);
} static void SaveAssembly()
{
Type t = typeBuilder.CreateType(); //完成Type,这是必须的
assemblyBuilder.Save(binaryName);
}
}
}