J'essaie d'utiliser Reflection.Emit en C# pour émettre un bloc using (x) { ... }
. Au point où je suis en code, j'ai besoin de prendre le sommet actuel de la pile, qui est un objet qui implémente IDisposable, le stocke dans une variable locale, implémente un bloc using sur cette variable, puis à l'intérieur il ajouter un peu plus de codeL'utilisation de Reflection.Emit pour émettre un bloc "using (x) {...}"?
Voici un exemple de C# morceau de code que j'ai essayé de compiler et de regarder dans le réflecteur (je peux faire face à cette dernière partie.):
public void Test()
{
TestDisposable disposable = new TestDisposable();
using (disposable)
{
throw new Exception("Test");
}
}
cela ressemble à ce réflecteur:
.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
}
Je n'ai aucune idée de la façon de traiter cette partie ".try ..." à la fin là en utilisant Reflection.Emit.
Quelqu'un peut-il me diriger dans la bonne direction?
Modifier: Après posé des questions sur le code par e-mail, je posterai mon code d'interface fluide, mais il ne va pas être beaucoup plus utile à personne, sauf si vous prenez certains de mes bibliothèques de classes, et c'est un peu de code aussi. Le code avec lequel je luttais faisait partie de mon projet IoC, et j'avais besoin de générer une classe pour implémenter la journalisation automatique des appels de méthodes sur un service, essentiellement une classe de décorateur pour les services qui génèrent automatiquement le code.
La boucle principale de la méthode, qui met en oeuvre toutes les méthodes d'interface, est la suivante:
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();
}
EmitUsing recrache la BeginExceptionBlock que Jon a répondu avec, de sorte que ce que je devais savoir.
Le code ci-dessus provient de LoggingDecorator.cs, les extensions IL sont principalement dans ILGeneratorExtensions.Designer.cs et d'autres fichiers dans l'espace de noms LVK.Reflection.
Oui, c'était ce que je recherchais. Merci. Je posterai le code si quelqu'un d'autre cherche quelque chose comme ça. –
A la réflexion, je vais poster mon code, j'ai une bibliothèque complète de méthodes d'extension pour Reflection.Emit donc je vais devoir tout réécrire, je le ferai si quelqu'un le demande, mais mon code actuel ne sera probablement utile à personne d'autre qu'à moi. –