Bir using (x) { ... }
bloğunu yayınlamak için C# de Reflection.Emit'i kullanmaya çalışıyorum.Bir "kullanarak (x) {...}" bloğu çıkarmak için Reflection.Emit'i kullanma?
Kodda olduğum noktada, IDisposable uygulayan, bunu yerel bir değişkende saklayan, bu değişken üzerinde bir kullanım bloğu uygulayan ve sonra içeride bulunan yığının geçerli üst düzeyini almam gerekiyor. o biraz daha kod eklemek İşte
ben derlemek ve yansıtıcı içinde bakmak çalıştı kod örnek C# parçası (bu son bölümü ile başa çıkabilirim.): Bu yansıtıcı içinde şuna benzerpublic 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'i kullanırken oradaki ".try ..." parçasının nasıl ele alınacağına dair hiçbir fikrim yok.
Birisi bana doğru yönde işaret edebilir mi?
Düzenleme: sonrası burada benim akıcı arayüz kodu göndeririz, e-posta yoluyla kodu hakkında sordum, ama sen benim sınıf kütüphanelerinin bazı kapmak sürece kimseye çok kullanmak gitmiyor ve bu da biraz kod. Çatıştığım kod, IoC projemin bir parçasıydı ve bir hizmeti temelde kodun otomatik olarak oluşturulduğu hizmetler için bir dekoratör sınıfının otomatik olarak günlüğe kaydedilmesi için bir sınıf oluşturmam gerekiyordu.
tüm metodları uygulayan yöntemin ana döngü, şudur ki:
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();
}
bilmem gerekeni yüzden EmitUsing Jon ile cevap BeginExceptionBlock tükürür.
Yukarıdaki kod LoggingDecorator.cs'dan, IL uzantıları çoğunlukla ILGeneratorExtensions.Designer.cs ve diğer dosyalar LVK.Reflection ad alanındadır.
Evet, peşindeyim buydu. Teşekkürler. Kimse böyle bir şey için bakarsa kodu gönderirim. –
İkinci düşünce üzerine, kodumu yayınlamaya bırakacağım, Reflection.Emit için kapsamlı bir uzantı yöntemleri kütüphanesi var, bu yüzden hepsini yeniden yazmam gerekecek, birisi sorarsa yapacağım, ama şu anki kodum Muhtemelen benim için başkalarına yardımcı olmayacaktır. –