I want to add method body without going through Emit statements. Similar to:
public static void Replicate<T>(this MethodBuilder methodBuilder, Func<T> func)
{
var body = func.Method.GetMethodBody();
var instructions = body.GetILAsByteArray();
methodBuilder.CreateMethodBody(instructions, instructions.Length);
}
var methodBuilder = typeBuilder.DefineMethod("GetExtensionCollection", MethodAttributes.Public, typeof(Stream), Type.EmptyTypes);
methodBuilder.Replicate(() =>
{
var assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceStream(assembly.GetName().Name + ".Extensions.xml");
});
When I decompile the generated assembly using dnSpy, the IL code is completely wrong, and the C# code throws exception.
I have also tried the following, based on Create a copy of method from IL and I have modified it to use Mono.Reflection:
public static void Replicate<T>(this MethodBuilder methodBuilder, Func<T> func)
{
var il = methodBuilder.GetILGenerator();
foreach (var local in func.Method.GetMethodBody().LocalVariables)
il.DeclareLocal(local.LocalType);
foreach (var instrcustion in func.Method.GetInstructions())
{
if (instrcustion.OpCode.OperandType == OperandType.InlineBrTarget)
{
il.Emit(instrcustion.OpCode, Convert.ToInt32(instrcustion.Operand));
continue;
}
if (instrcustion.OpCode.OperandType == OperandType.ShortInlineBrTarget)
{
continue;
}
if (instrcustion.OpCode.OperandType == OperandType.InlineString)
{
il.Emit(instrcustion.OpCode, instrcustion.Operand.ToString());
continue;
}
if (instrcustion.OpCode.OperandType == OperandType.InlineType)
{
il.Emit(instrcustion.OpCode, instrcustion.Operand as Type);
continue;
}
if (instrcustion.OpCode.FlowControl == FlowControl.Call)
{
var methodInfo = instrcustion.Operand as MethodInfo;
if (methodInfo == func.Method)
il.Emit(instrcustion.OpCode, methodBuilder);
else
il.Emit(instrcustion.OpCode, methodInfo);
continue;
}
il.Emit(instrcustion.OpCode);
}
}
This one works, but I need:
- Preferably get the first
Replicate
to work - If not successful, build a comprehensive version of the second
Replicate