Bir DynamicMethod ve ilişkili IL garbage-collector tarafından referans olarak verilmediği zaman toplanır. Yani belleği doldurmadan dinamik olarak methodlar oluşturup durabilirsiniz.
DynamicMethod Örneği:
static void Main()
{
var dynMeth = new DynamicMethod("Foo", null, null, typeof(Program));
ILGenerator gen = dynMeth.GetILGenerator();
gen.EmitWriteLine("Hello World");
gen.Emit(OpCodes.Ret);
dynMeth.Invoke(null, null);
}
Method her zaman OpCodes.Ret ile biter. Return anlamına gelir.
EmitWriteLine metodu ILGenerator da bir dizi düşük seviyedeki opcode ları yayınlayan kısayoldur.
Aynı sonucu Emit WriteLine ile alamak için aşağıda ki gibi kodu değiştirebiliriz.
dynMeth = new DynamicMethod("Bar", null, null, typeof(Program));
gen = dynMeth.GetILGenerator();
MethodInfo mi = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
gen.Emit(OpCodes.Ldstr, "Hello World2");
gen.Emit(OpCodes.Call, mi);
gen.Emit(OpCodes.Ret);
dynMeth.Invoke(null,null);
Public olmayan methodlara ulaşmamız için örnek:
var dynMeth = new DynamicMethod("Tar", null, null, typeof(Program));
ILGenerator gen = dynMeth.GetILGenerator();
MethodInfo privateMethod = typeof(Program).GetMethod("HelloWorld", BindingFlags.NonPublic | BindingFlags.Static);
gen.Emit(OpCodes.Call, privateMethod);
gen.Emit(OpCodes.Ret);
dynMeth.Invoke(null, null);
Parametre ile Toplama İşlemi
using System;
using System.Reflection.Emit;
namespace ConsoleApp2
{
class Program
{
delegate int BinaryFunction(int n1, int n2);
static void Main()
{
var dynMeth = new DynamicMethod("Sum",
typeof(int), //Return Type = int
new[] { typeof(int), typeof(int) }, // Parameter Types = int, int
typeof(Program));
ILGenerator gen = dynMeth.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Add);
gen.Emit(OpCodes.Ret);
// Usage 1
var result = (int)dynMeth.Invoke(null, new object[] { 4, 5 });
Console.WriteLine(result);
//Usage 2 // Comman Way
BinaryFunction sumCommonWay = (BinaryFunction)dynMeth.CreateDelegate(typeof(BinaryFunction));
result = sumCommonWay(3, 4);
Console.WriteLine(result);
Console.ReadKey();
}
}
}
// Yerel Değişken Ekleme ve Döngüler
using System;
using System.Reflection.Emit;
namespace ConsoleApp2
{
class Program
{
static void Main()
{
var dynMeth = new DynamicMethod("Sum4", typeof(int), new[] { typeof(int) }, typeof(Program));
ILGenerator gen = dynMeth.GetILGenerator();
Label startLoop = gen.DefineLabel(); // Declare labels
Label endLoop = gen.DefineLabel();
LocalBuilder i = gen.DeclareLocal(typeof(int)); // int i for index
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Stloc, i);
LocalBuilder sum = gen.DeclareLocal(typeof(int)); // int sum for from 0 to i initial value
gen.Emit(OpCodes.Ldc_I4,0);
gen.Emit(OpCodes.Stloc, sum); // set value for local sum
gen.MarkLabel(startLoop);
gen.Emit(OpCodes.Ldc_I4, 1); // Load 10 onto eval stack
gen.Emit(OpCodes.Ldloc, i); // Load x onto eval stack
gen.Emit(OpCodes.Bgt, endLoop); // if (x > 10) goto endLoop
gen.Emit(OpCodes.Ldloc, i); // Load x onto eval stack
gen.Emit(OpCodes.Ldloc, sum); // Load x onto eval stack
gen.Emit(OpCodes.Add);
gen.Emit(OpCodes.Stloc, sum); // Save result back to x
gen.Emit(OpCodes.Ldloc, i); // Load x onto eval stack
gen.Emit(OpCodes.Ldc_I4, -1); // Load -1 onto the stack
gen.Emit(OpCodes.Add); // Add them together
gen.Emit(OpCodes.Stloc, i); // Save result back to x
gen.Emit(OpCodes.Br, startLoop); // return to start of loop
gen.MarkLabel(endLoop);
gen.Emit(OpCodes.Ldloc, sum); //
gen.Emit(OpCodes.Ret);
var res = (int)dynMeth.Invoke(null, new object[] { 15 });
Console.WriteLine(res);
Console.ReadKey();
}
}
}
Detayl Bilgi İçin Kaynak : https://www.amazon.com/C-7-0-Nutshell-Definitive-Reference/dp/1491987650