ابحث عن قيم الوسيطة لاستدعاء الطريقة في IL

StackOverflow https://stackoverflow.com/questions/857593

  •  21-08-2019
  •  | 
  •  

سؤال

لدي عدة طرق خاصة، وأريد تحليل ما يستدعيه في التجميع المترجم.

مثال:

public static class SrcHelper {
    [MySpecialMethod]
    [Conditional( "DEBUG" )]
    public static void ToDo( params object[] info ) {
        /* do nothing */
        /* this method is not called when code is compiled in RELEASE mode */
    }
}
// ... somewhere else in another assembly ...
Array CreateArraySampleMethod( int size ) {
    // This call has only informative character. No functionality is required.
    SrcHelper.ToDo( "Should create array of ", typeof( MyClass ), " with specified size." );
    throw new NotImplementedException();
}

من هذا الرمز المترجم ، أريد الحصول على قيم الوسيطة {"يجب إنشاء مجموعة من" ، myClass ، "بحجم محدد." }.حاولت استخدام Cecil من Mono، ووجدت تعليمات طريقة الاتصال "ToDo".ولكن الآن أنا في حيرة من أمري حول كيفية تحديد التعليمات بقيم الوسيطة.

أعلم أنه قد يكون هناك موقف معقد، ولا يمكن حل قيمة بعض الحجج.لكني أحتاج إلى حل القيم الثابتة فقط - فهذا يكفي لغرضي.

شكرًا.

يحرر:يجب استخدام طريقة "ToDo" (وما شابهها) كبديل للتعليقات ( //, /* ...*/ )، وبعد التجميع، يجب تحليل IL والتوثيق الذي تم إنشاؤه تلقائيًا وقائمة المهام لتجميع الخرسانة.

هل كانت مفيدة؟

المحلول

يعد إنشاء التعليمات البرمجية أمرًا مربكًا إلى حد ما ولكن يمكن إجراؤه في حالات بسيطة:

تجميع:

public static void Main(string[] args)
{
    Console.WriteLine("", // ignore this argument
       "Should create array of ", typeof(int), " with specified size." "x");
}

(إضافة "x" لإجبارها على استخدام التحميل الزائد للمعلمات)

يعطي

.method public hidebysig static void Main(string[] args) cil managed
{
    .custom instance void [mscorlib]System.STAThreadAttribute::.ctor()
    .maxstack 4
    .locals init (
        [0] object[] objArray)
    L_0000: ldstr ""
    L_0005: ldc.i4.4 
    L_0006: newarr object
    L_000b: stloc.0 
    L_000c: ldloc.0 
    L_000d: ldc.i4.0 
    L_000e: ldstr "Should create array of "
    L_0013: stelem.ref 
    L_0014: ldloc.0 
    L_0015: ldc.i4.1 
    L_0016: ldtoken int32
    L_001b: call class [mscorlib]System.Type 
                [mscorlib]System.Type::GetTypeFromHandle(
                    valuetype [mscorlib]System.RuntimeTypeHandle)
    L_0020: stelem.ref 
    L_0021: ldloc.0 
    L_0022: ldc.i4.2 
    L_0023: ldstr " with specified size."
    L_0028: stelem.ref 
    L_0029: ldloc.0 
    L_002a: ldc.i4.3 
    L_002b: ldstr "x"
    L_0030: stelem.ref 
    L_0031: ldloc.0 
    L_0032: call void [mscorlib]System.Console::WriteLine(string, object[])
    L_0037: ret 
}

لذلك ما عليك فعله هو تحليل الملف لاكتشاف الوسائط التي يتم دفعها إلى المصفوفة التي أنشأها المترجم.هرطقة هشة ولكن قد يكفي أن نقول:

  1. ابحث عن اتصال بـ "طريقتي".
  2. العثور على أقرب كائن newarr السابق
  3. خذ كل ldstr وldtoken بينهما وافترض أنهما الوسيطتان.

هذا أمر تقريبي ولكنه قد يكون كافيًا لاحتياجاتك.

سوف يمنحك أسلوب أسلوب AOP ما تريد مدة العرض ببساطة عن طريق استخدام كل مكالمة لتفريغ القيم ولكن في وقت قصير، يكون النهج أعلاه هو خيارك الواقعي الوحيد بالنظر إلى IL فقط.

قد يكون الكود الذي تم إنشاؤه مختلفًا تمامًا في إصدارات الإصدار، ولن تتمكن من اكتشاف المصفوفة التي تم إنشاؤها تلقائيًا مقابل شخص يقوم بإنشائها بشكل صريح بنفسه (والذي قد يكون بعيدًا عن موقع الاتصال أو حتى في طريقة/منشئ/فئة مختلفة.

شرط

يجب أن أشير بعد التعديل إلى سبب رغبتك في القيام بذلك أن التعليقات التوضيحية المستندة إلى السمة هي حل أفضل بكثير، لا أستطيع أن أرى سبب رغبتك في القيام بذلك في الطريقة عندما يمكنك إسنادها مباشرة...

نصائح أخرى

لست متأكدا مما تقصده.ومع ذلك، لاحظ أن وظيفتك تحصل بالفعل فقط واحد دعوى:مجموعة.وهذا ما تحصل عليه في IL أيضًا. داخل الدالة، يمكنك التنقل عبر المصفوفة للحصول على قيمها:

public static void ToDo( params object[] info ) {
    foreach (object x in info)
        Console.WriteLine(x);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top