好吧,我们说这个c#代码:
public override void Write(XDRDestination destination)
{
destination.WriteInt(intValue);
destination.WriteBool(boolValue);
destination.WriteFixedString(str1, 100);
destination.WriteVariableString(str2, 100);
}
Run Code Online (Sandbox Code Playgroud)
IL:
.method public hidebysig virtual instance void
Write(class [XDRFramework]XDRFramework.XDRDestination destination) cil managed
{
// Code size 53 (0x35)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.0
IL_0002: call instance int32 LearnIL.Test1::get_intValue()
IL_0007: callvirt instance void [XDRFramework]XDRFramework.XDRDestination::WriteInt(int32)
IL_000c: ldarg.1
IL_000d: ldarg.0
IL_000e: call instance bool LearnIL.Test1::get_boolValue()
IL_0013: callvirt instance void [XDRFramework]XDRFramework.XDRDestination::WriteBool(bool)
IL_0018: ldarg.1
IL_0019: ldarg.0
IL_001a: call instance string LearnIL.Test1::get_str1()
IL_001f: ldc.i4.s 100
IL_0021: callvirt instance void [XDRFramework]XDRFramework.XDRDestination::WriteFixedString(string,
uint32) …Run Code Online (Sandbox Code Playgroud) 在我正在制作的DynamicMethod中,我发现了"操作可能会破坏运行时的稳定性"的原因,虽然我很容易修复它,但它给我留下了一个看似简单的问题:
以下是示例程序.运行此命令时,它将在编译方法时因"操作可能使运行时不稳定"异常而崩溃.
只是通过改变声明为变量的变量的类型TestClass来解决问题Object,但我仍然想知道如何将引用转换为代码中的相应类型.
在代码中我标记了一个带有星号的行.在那一点上我可以发出什么代码来使Object堆栈上的TestClass引用成为引用,以便方法调用将通过?
请注意,我知道这是产生问题的方法调用,如果我完全注释掉这些行,那么变量的类型无关紧要,该方法被编译并执行正常.
这是代码.
using System;
using System.Reflection.Emit;
namespace ConsoleApplication9
{
public class TestClass
{
public void TestMethod() { }
}
class Program
{
static void Main(string[] args)
{
Type type = typeof(TestClass);
DynamicMethod method = new DynamicMethod("", typeof(Object), null);
ILGenerator il = method.GetILGenerator();
LocalBuilder variable = il.DeclareLocal(typeof(Object));
// Construct object
il.Emit(OpCodes.Newobj, type.GetConstructor(new Type[0]));
il.Emit(OpCodes.Stloc, variable);
// Call Test method
il.Emit(OpCodes.Ldloc, variable);
// ***************************************** what do I do here? …Run Code Online (Sandbox Code Playgroud) 我试图通过System.Reflection和System.Reflection.Emit使if-else在IL中工作.这是我目前拥有的代码:
Label inequality = new System.Reflection.Emit.Label();
Label equality = new System.Reflection.Emit.Label();
Label end = new System.Reflection.Emit.Label();
var method = new DynamicMethod("dummy", null, Type.EmptyTypes);
var g = method.GetILGenerator();
g.Emit(OpCodes.Ldstr, "string");
g.Emit(OpCodes.Ldstr, "string");
g.Emit(OpCodes.Call, typeof(String).GetMethod("op_Equality", new Type[]{typeof(string), typeof(string)}));
g.Emit(OpCodes.Ldc_I4, 0);
g.Emit(OpCodes.Ceq);
g.Emit(OpCodes.Brtrue_S, inequality);
g.MarkLabel(inequality); //HERE it throws exception
g.Emit(OpCodes.Ldstr, "Specified strings are different.");
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[]{typeof(string)}));
g.Emit(OpCodes.Br_S, end);
g.Emit(OpCodes.Brfalse_S, equality);
g.MarkLabel(equality);
g.Emit(OpCodes.Ldstr, "Specified strings are same.");
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
g.Emit(OpCodes.Br_S, end);
g.MarkLabel(end);
g.Emit(OpCodes.Ret);
var action = (Action)method.CreateDelegate(typeof(Action)); …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个.NET应用程序,它可以分析其他.NET进程并列出它们所做的所有调用,包括传递参数的值.
我知道用"ICorProfilerCallback2"之类的东西编写我自己的探查器可以对此有所帮助,但这似乎是一项非常具有挑战性的任务.在进行之前,我想确保这是实现这一目标的唯一方法.
我看着开源.NET剖析和一致好评,如部分覆盖,CLR探查器4.0版等,但他们都不似乎提供了一个管理API来做到这一点,他们做的远远超过我所需要的(内存分析等).
有没有其他方法可以做到这一点?一种更简单的方法来进行这种分析?我在这里有什么选择?
我有一个动态创建的程序集,一个模块,一个类和一个动态生成的方法。
AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(...);
ModuleBuilder module = assembly.DefineDynamicModule(...);
TypeBuilder tb = module.DefineType(...);
MethodBuilder mb = tb.DefineMethod(...);
ILGenerator gen = mb.GetILGenerator();
Run Code Online (Sandbox Code Playgroud)
如何调试使用生成的方法代码ILGenerator?我使用Visual Studio 2012调试器,但它只是逐步执行方法调用。
每次我在IL中使用它们:br_S,ldc_i4_S,ldarg_S等等......所以我只需要问这个问题:
我的意思是......如果你是从IL到本地汇编程序的JIT语言,它在性能方面应该不重要,对吧?那么这些"短手"符号的目的是什么?是仅仅因为IL二进制文件中的字节数较少(例如作为压缩机制)还是有其他原因?
如果它只是一个压缩机制,为什么不使用压缩算法,如deflate?
我正在尝试将这个简单的类转换为IL代码:
public class IL {
Dictionary<string, int> props = new Dictionary<string, int>() { {"1",1} };
}
Run Code Online (Sandbox Code Playgroud)
事实上,ILDasm在尝试使用Emit动态创建类之前,我曾经知道IL指令.结果显示:
.class public auto ansi beforefieldinit IL
extends [mscorlib]System.Object
{
.field private class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32> props
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
//
.maxstack 4
.locals init (class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32> V_0)
IL_0000: ldarg.0
IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldstr "1"
IL_000d: ldc.i4.1
IL_000e: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::Add(!0,
!1)
IL_0013: ldloc.0 …Run Code Online (Sandbox Code Playgroud) .method public static void Test<class T>(object A_0) cil managed
{
// Code size 13 (0xd)
.maxstack 1
.locals init (!!T V_0)
IL_0000: ldarg.0
IL_0001: isinst !!T
IL_0006: unbox.any !!T
IL_000b: stloc.0
IL_000c: ret
} // end of method DemoType::Test
Run Code Online (Sandbox Code Playgroud)
相同的C#代码是:
public static void Test<T>(object o) where T : class
{
T t = o as T;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
为什么unbox.any被称为?如果你这样做
var a = father as child
Run Code Online (Sandbox Code Playgroud)
isinst intruction将调用而不是unbox.any,如果我将删除泛型定义并且我将尝试将(isinst)对象强制转换为某个类,则不会调用unbox.any.
也许因为泛型定义而调用unbox.any,所以在这种情况下unbox.any需要抛出NullReferenceException,因为isinst指令的答案为此转换返回null.请参阅unbox_any.如果您尝试运行此代码,您将看到没有抛出任何异常.
更新
我可以理解unbox_any因为对象类型参数,它尝试在isinst检查后将其强制转换为具体类型.也许仿制药也会影响.
我的问题是,为什么不在unbox.any中抛出异常,如果我们尝试unbox到T的obj是null?
文档说:"如果obj是一个空引用,则抛出NullReferenceException."
我怀疑这两个方面;
第一;
Test test = new Test();
result = test.DoWork(_param);
Run Code Online (Sandbox Code Playgroud)
第二个;
result = new Test().DoWork(_param);
Run Code Online (Sandbox Code Playgroud)
如果我们不将新创建的实例分配给变量并直接调用该方法会发生什么?
我看到IL代码的两种方式有所不同.
下面这个是第一个c#代码的IL输出
IL_0000: ldstr "job "
IL_0005: stloc.0
IL_0006: newobj instance void Works.Test::.ctor()
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: ldloc.0
IL_000e: callvirt instance string Works.Test::DoWork(string)
IL_0013: pop
IL_0014: ret
Run Code Online (Sandbox Code Playgroud)
这个是第二个c#代码的IL输出
IL_0000: ldstr "job "
IL_0005: stloc.0
IL_0006: newobj instance void Works.Test::.ctor()
IL_000b: ldloc.0
IL_000c: call instance string Works.Test::DoWork(string)
IL_0011: pop
IL_0012: ret
Run Code Online (Sandbox Code Playgroud)
你能告诉我吗?
我试图使用Fody来包装从具有常见异常格式的方法抛出的所有异常.
所以我添加了所需的接口声明和类实现,如下所示:
using System;
using System.Diagnostics;
using System.Reflection;
using System.Threading.Tasks;
[module: MethodDecorator]
public interface IMethodDecorator
{
void Init(object instance, MethodBase method, object[] args);
void OnEntry();
void OnExit();
void OnException(Exception exception);
void OnTaskContinuation(Task t);
}
[AttributeUsage(
AttributeTargets.Module |
AttributeTargets.Method |
AttributeTargets.Assembly |
AttributeTargets.Constructor, AllowMultiple = true)]
public class MethodDecorator : Attribute, IMethodDecorator
{
public virtual void Init(object instance, MethodBase method, object[] args) { }
public void OnEntry()
{
Debug.WriteLine("base on entry");
}
public virtual void OnException(Exception exception)
{
Debug.WriteLine("base on exception"); …Run Code Online (Sandbox Code Playgroud)