使用Reflection.emit发射“使用(x){…}”块?
-
24-10-2019 - |
题
我正在尝试使用反射。 using (x) { ... }
堵塞。
在我的代码中,我需要将当前的堆栈顶部取下,该堆栈是一个实现IDISPOSABLE的对象,将其存储在本地变量中,在该变量上实现a使用块,然后在内部添加更多代码(我可以处理最后一部分。)
这是我尝试编译并在反射器中查看的示例C#件件:
public void Test()
{
TestDisposable disposable = new TestDisposable();
using (disposable)
{
throw new Exception("Test");
}
}
在反射器中看起来像这样:
.method public hidebysig instance void Test() cil managed
{
.maxstack 2
.locals init (
[0] class LVK.Reflection.Tests.UsingConstructTests/TestDisposable disposable,
[1] class LVK.Reflection.Tests.UsingConstructTests/TestDisposable CS$3$0000,
[2] bool CS$4$0001)
L_0000: nop
L_0001: newobj instance void LVK.Reflection.Tests.UsingConstructTests/TestDisposable::.ctor()
L_0006: stloc.0
L_0007: ldloc.0
L_0008: stloc.1
L_0009: nop
L_000a: ldstr "Test"
L_000f: newobj instance void [mscorlib]System.Exception::.ctor(string)
L_0014: throw
L_0015: ldloc.1
L_0016: ldnull
L_0017: ceq
L_0019: stloc.2
L_001a: ldloc.2
L_001b: brtrue.s L_0024
L_001d: ldloc.1
L_001e: callvirt instance void [mscorlib]System.IDisposable::Dispose()
L_0023: nop
L_0024: endfinally
.try L_0009 to L_0015 finally handler L_0015 to L_0025
}
我不知道如何在使用reflection.emit时在其中的末端处理“。
有人可以将我指向正确的方向吗?
编辑: :在通过电子邮件询问代码后,我将在此处发布我的流利接口代码,但是除非您抓住我的一些课堂库,否则对任何人都不会有太多使用,这也是一定的代码。我与之挣扎的代码是我的IOC项目的一部分,我需要生成一个类以在服务上实现方法调用的自动记录,这基本上是一种用于自动生成代码的服务的装饰器类。
实现所有接口方法的方法的主要循环是:
foreach (var method in interfaceType.GetMethods())
{
ParameterInfo[] methodParameters = method.GetParameters();
var parameters = string.Join(", ", methodParameters
.Select((p, index) => p.Name + "={" + index + "}"));
var signature = method.Name + "(" + parameters + ")";
type.ImplementInterfaceMethod(method).GetILGenerator()
// object[] temp = new object[param-count]
.variable<object[]>() // #0
.ldc(methodParameters.Length)
.newarr(typeof(object))
.stloc_0()
// copy all parameter values into array
.EmitFor(Enumerable.Range(0, methodParameters.Length), (il, i) => il
.ldloc_0()
.ldc(i)
.ldarg_opt(i + 1)
.EmitIf(methodParameters[i].ParameterType.IsValueType, a => a
.box(methodParameters[i].ParameterType))
.stelem(typeof(object))
)
// var x = _Logger.Scope(LogLevel.Debug, signature, parameterArray)
.ld_this()
.ldfld(loggerField)
.ldc(LogLevel.Debug)
.ldstr(signature)
.ldloc(0)
.call_smart(typeof(ILogger).GetMethod("Scope", new[] { typeof(LogLevel), typeof(string), typeof(object[]) }))
// using (x) { ... }
.EmitUsing(u => u
.ld_this()
.ldfld(instanceField)
.ldargs(Enumerable.Range(1, methodParameters.Length).ToArray())
.call_smart(method)
.EmitCatch<Exception>((il, ex) => il
.ld_this()
.ldfld(loggerField)
.ldc(LogLevel.Debug)
.ldloc(ex)
.call_smart(typeof(ILogger).GetMethod("LogException", new[] { typeof(LogLevel), typeof(Exception) }))
)
)
.ret();
}
发出的吐出了乔恩回答的beginexceptionblock,所以这就是我需要知道的。
以上代码来自 loggingdecorator.cs, ,IL扩展大多在 ilgeneratorextensions.designer.cs, ,以及其他文件 LVK。反射 名称空间。
解决方案
是 ILGenerator.BeginExceptionBlock
你追求什么?文档中的示例表明这是正确的方法...
其他提示
这是代码中的一个示例。
ILGenerator ilg = ...;
// Begin the 'try' block. The returned label is at the end of the 'try' block.
// You can jump there and any finally blocks will be executed.
Label block = ilg.BeginExceptionBlock();
// ... emit operations that might throw
ilg.BeginFinallyBlock();
// ... emit operations within the finally block
ilg.EndExceptionBlock();
不隶属于 StackOverflow