簡體   English   中英

如何將方法調用轉到自檢規則中的Introspector中的Action,Func或Delegate?

[英]How can I walk the method call to an Action, Func, or Delegate in introspector for a custom rule?

我正在編寫一個自定義規則,以驗證任何控件類型的構造函數調用初始化組件。

但是,當我遇到以下兩種情況時:

public Form1(int? testInt,bool testBool,bool testBool2)
        : this(false)
    {
        Action init = ( ) => InitializeComponent( );
        init();
    }
    public Form1(int? testInt, bool testBool, bool? testBool2)
        : this(false)
    {
        Action init = InitializeComponent;
        init( );
    }

我似乎無法通過init調用來看到在這些構造函數中調用了initializeComponent。 我知道這是一個極端的情況,不太可能發生,但是我想學習如何做。

反射器IL如下所示:

.method public hidebysig specialname rtspecialname instance void .ctor(valuetype [mscorlib]System.Nullable`1<int32> testInt, bool testBool, bool testBool2) cil managed
{
.maxstack 3
.locals init (
    [0] class [mscorlib]System.Action init,
    [1] class [mscorlib]System.Action CS$<>9__CachedAnonymousMethodDelegateb)
L_0000: ldnull 
L_0001: stloc.1 
L_0002: ldarg.0 
L_0003: ldc.i4.0 
L_0004: call instance void TestLibrary.Form1::.ctor(bool)
L_0009: nop 
L_000a: nop 
L_000b: ldloc.1 
L_000c: brtrue.s L_001d
L_000e: ldarg.0 
L_000f: ldftn instance void TestLibrary.Form1::<.ctor>b__a()
L_0015: newobj instance void [mscorlib]System.Action::.ctor(object, native int)
L_001a: stloc.1 
L_001b: br.s L_001d
L_001d: ldloc.1 
L_001e: stloc.0 
L_001f: ldloc.0 
L_0020: callvirt instance void [mscorlib]System.Action::Invoke()
L_0025: nop 
L_0026: nop 
L_0027: ret 
}


.method public hidebysig specialname rtspecialname instance void .ctor(valuetype [mscorlib]System.Nullable`1<int32> testInt, bool testBool, valuetype [mscorlib]System.Nullable`1<bool> testBool2) cil managed
{
.maxstack 3
.locals init (
    [0] class [mscorlib]System.Action init)
L_0000: ldarg.0 
L_0001: ldc.i4.0 
L_0002: call instance void TestLibrary.Form1::.ctor(bool)
L_0007: nop 
L_0008: nop 
L_0009: ldarg.0 
L_000a: ldftn instance void TestLibrary.Form1::InitializeComponent()
L_0010: newobj instance void [mscorlib]System.Action::.ctor(object, native int)
L_0015: stloc.0 
L_0016: ldloc.0 
L_0017: callvirt instance void [mscorlib]System.Action::Invoke()
L_001c: nop 
L_001d: nop 
L_001e: ret 
}

我正在這樣的構造函數:

        private Dictionary<Method, bool> _methodContainsInitCall;
public void VisitConstructorsRecursive(Method method, Method initializer)
    {
        Debug.Assert(_methodContainsInitCall.ContainsKey(method));
        var toVisit = new List<Method>( );
        foreach (var instruction in method.Instructions.Where(x => x.OpCode==OpCode.Call || x.OpCode== OpCode.Callvirt))
        {

            if (instruction.Value is Method)
            {
                //&&((Method)instruction.Value).FullName.Contains(".#ctor")
                var callMethod =(Method)instruction.Value;
                if (callMethod.FullName.StartsWith("System.Windows.Forms.Form.#ctor"))
                    continue;
                if (callMethod.IsStatic==false) //can not call instance method InitializeComponent in static method
                {
                    toVisit.Add(callMethod);
                }

                //
                //TestLibrary.Form1.#ctor(System.String)
            }
            if (instruction.Value is Method&&((Method)instruction.Value).FullName.EndsWith(".InitializeComponent"))
            {
                if (_constructorFoundInitializeCall.ContainsKey(method))
                    _constructorFoundInitializeCall[method]=true;
                _methodContainsInitCall[method]=true;
                return;
            }

        }
        foreach (var methodCall in toVisit)
        {
            if (_methodContainsInitCall.ContainsKey(methodCall))
            {
                if (_methodContainsInitCall[methodCall])
                {
                    _constructorFoundInitializeCall[initializer]=true;
                    return;
                }
            }
            else
            {
                _methodContainsInitCall.Add(methodCall, false);
                VisitConstructorsRecursive(methodCall, initializer);
            }


        }
    }

當對Action.Invoke()的虛擬調用發生時,它被標記為virtual和method.Instructions.Count ==0以及method.Body.Count==0

所以我調用初始化組件的指令隱藏在哪里,我可以驗證它實際上在被調用?

當遍歷組成構造函數的塊時,請注意CS $ <> 9__CachedAnonymousMethodDelegateb類型變量。 該類實際上包含調用InitializeComponent的已編譯委托。

如果要檢查這一點,請檢查該方法的本地方法,找到訪問編譯器生成的類型,然后您將發現它只有一個方法。 訪問該方法以檢查它是否調用了初始化組件。

問題在於,檢測這些類型的類的唯一方法是按名稱。 C#和VB.NET編譯器使用不同的命名方案來存儲這些匿名委托。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM