Official website address: https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.emit.ilgenerator.emit?view=netcore-3.1
First, know Emit
Emit manner using methods may be written in C # code and generate IL code execution.
Second, simple to use
Example: create an assembly, create a module, create a class, create a constructor, create and invoke methods
static void Main(string[] args) { // -- 创建程序集 AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Example.Generator"), AssemblyBuilderAccess.RunAndCollect); // -- 创建模块 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Generators"); // -- 创建 Generator 类 TypeBuilder typeBuilder = moduleBuilder.DefineType("Generator"); // -- 创建构造函数 ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); // - filling the constructor of IL codes need to perform the ILGenerator constructGenerator = constructorBuilder.GetILGenerator (); // - definition of a string constructGenerator.Emit (OpCodes.Ldstr, "Building the logic code constructor by the Emit " ); / / - call Console.WriteLine () output words constructGenerator.Emit (OpCodes.Call, typeof (Console) .GetMethod ( " the WriteLine " , new new the Type [] { typeof ( String )})); // - return constructGenerator. EMIT (OpCodes.Ret); // - create a method MethodBuilder method = typeBuilder.DefineMethod (" The Start " , MethodAttributes.Public, typeof ( void ), new new the Type [] { typeof ( String )}); // - declare a method parameter name name method.DefineParameter ( 0 , ParameterAttributes.None, " name " ) ; // - method of preparation of IL code inside the ILGenerator methodGenerator = method.GetILGenerator (); // - incoming print parameter name methodGenerator.Emit (OpCodes.Ldarg_1); methodGenerator.Emit (OpCodes.Call, typeof (Console ) .GetMethod ( " the WriteLine", new Type[] { typeof(string) })); methodGenerator.Emit(OpCodes.Ret); // -- 创建实例 Type instance = typeBuilder.CreateType(); object proxy = Activator.CreateInstance(instance);
// -- 调用 MethodInfo methodInfo = proxy.GetType().GetMethod("Start"); methodInfo.Invoke(proxy, new string[] { "Hello Elson" }); Console.ReadKey(); }
Third, emphasis
constructGenerator.Emit (OpCodes.Ldstr, " Building the logic code constructor by the Emit " ); constructGenerator.Emit (OpCodes.Call, typeof (Console) .GetMethod ( " the WriteLine " , new new the Type [] { typeof ( String )} )); constructGenerator.Emit (OpCodes.Ret);
OpCodes.Ldstr:Pushes a new object reference to a string literal stored in the metadata.
Can be understood as: String A = "Content"
OpCodes.Call:Calls the method indicated by the passed method descriptor.
It can be understood as: call the method as described above.
The way we call the original method is: Console.WriteLine ( "Content"); and using Emit calls the method requires a description of the method: class type, method name, parameter types.
OpCodes.Ret:Returns from the current method, pushing a return value (if present) from the callee's evaluation stack onto the caller's evaluation stack.
It can be understood as: return value
// - define a method: Method name, access level, characteristic method, the return type, argument types
MethodBuilder = typeBuilder.DefineMethod Method ( " the Start " , MethodAttributes.Public, typeof ( void ), new new the Type [] { typeof ( String )}); // - declare a method parameters: parameter index, characteristic parameter, the parameter name method.DefineParameter ( 0 , ParameterAttributes.None, " name " ); the ILGenerator methodGenerator = method.GetILGenerator (); methodGenerator.Emit ( OpCodes.Ldarg_1); methodGenerator.Emit (OpCodes.Call, typeof (Console) .GetMethod ( " the WriteLine", new Type[] { typeof(string) })); methodGenerator.Emit(OpCodes.Ret);
OpCodes.Ldarg_1:Loads the argument at index 1 onto the evaluation stack.
Gets the parameters on the parameter index 1 position, if not a static method, OpCodes.Ldarg_0 acquisition is the this , the current object instance
class Example { public void GetContent(string content) { //Codes.Ldarg_0 = Example var _this = this; //Codes.Ldarg_1 = content var param = content } }
IV Conclusion
Everybody is welcome to correct me, common learning progress!
谦良恭卑,信诚实至;
生活不易,共勉同求。