Я хочу добавить тело метода без прохождения операторов Emit. Аналогично:
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");
});
Когда я декомпилирую сгенерированную сборку с использованием dnSpy, код IL полностью неверен, а код C# вызывает исключение.
Я также попробовал следующее на основе Создайте копию метода из IL , и я изменил 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);
}
}
Этот работает, но мне нужно:
- Желательно, чтобы первый
Replicate
работал - Если не удастся, создайте полную версию второй
Replicate