このコードがあるとしましょう:
Action<int> gf = k => { };
Action<int> gfa = k => { k++; };
gf
本文やステートメントがないことをどのように判断できますか?
内のステートメントの数を取得することは可能Action
ですか?
GetNumberOfStatements(gf)
which shouldに似たものreturn 0
。
または多分 HasEmptyBody(gf) べきreturn true
です;
.Net のデリゲートは、関数ポインターにすぎません。.Net メソッドに含まれる C# ステートメントの数がわからないのと同様に、.Net デリゲートに含まれるステートメントの数もわかりません。その理由の 1 つは、メソッドが必ずしも C# やステートメントの概念を持つ他の言語でコーディングされているとは限らないためです。オペコードベースのILに直接書き込むことができます
編集:ビルドサーバーが再起動するのを待っている間に、これを少し修正することにしました...
私は実際に私の「ユーティリティライブラリ」の周りに何かを置いていますが、それはおそらくあなたを助けるかもしれません.
public static void DumpMethod(Delegate method)
{
var mb = method.Method.GetMethodBody();
var il = mb.GetILAsByteArray();
var opCodes = typeof(System.Reflection.Emit.OpCodes)
.GetFields()
.Select(fi => (System.Reflection.Emit.OpCode)fi.GetValue(null));
var mappedIL = il.Select(op => opCodes.FirstOrDefault(opCode => opCode.Value == op));
var ilWalker = mappedIL.GetEnumerator();
while(ilWalker.MoveNext())
{
var mappedOp = ilWalker.Current;
if(mappedOp.OperandType != System.Reflection.Emit.OperandType.InlineNone)
{
var byteCount = 0;
long operand = 0;
switch(mappedOp.OperandType)
{
case System.Reflection.Emit.OperandType.InlineI:
case System.Reflection.Emit.OperandType.InlineBrTarget:
case System.Reflection.Emit.OperandType.InlineMethod:
case System.Reflection.Emit.OperandType.InlineField:
case System.Reflection.Emit.OperandType.InlineSig:
case System.Reflection.Emit.OperandType.InlineString:
case System.Reflection.Emit.OperandType.InlineType:
case System.Reflection.Emit.OperandType.InlineSwitch:
byteCount = 4;
break;
case System.Reflection.Emit.OperandType.InlineI8:
case System.Reflection.Emit.OperandType.InlineR:
byteCount = 8;
break;
}
for(int i=0; i < byteCount; i++)
{
ilWalker.MoveNext();
operand |= ((long)ilWalker.Current.Value) << (8 * i);
}
Console.WriteLine("{0} {1}", mappedOp.Name, operand);
}
else
{
Console.WriteLine("{0}", mappedOp.Name);
}
}
}
テスト装置:
Func<int,int> addOne = i => i + 1;
DumpMethod(addOne);
Console.WriteLine();
Func<int,string> stuff = i =>
{
var m = 10312;
var j = i + m;
var k = j * j + i;
var asStr = k.ToString();
return asStr;
};
DumpMethod(stuff);
出力:
ldarg.0
ldc.i4.1
add
ret
ldc.i4 10312
stloc.0
ldarg.0
ldloc.0
add
stloc.1
ldloc.1
ldloc.1
mul
ldarg.0
add
stloc.2
ldloca.s 0
ldarg.0
call 167772167
stloc.3
ldloc.3
ret