2011-01-21 8 views
28

क्या अभिव्यक्ति वृक्ष पर संकलन() को कॉल करते समय आईएल कोड उत्पन्न करना संभव है? इस बहुत ही सरल उदाहरण पर विचार करें:संकलित अभिव्यक्ति से उत्पन्न आईएल कोड को देखकर

class Program 
{ 
    public int Value { get; set; } 

    static void Main(string[] args) 
    { 
     var param = Expression.Parameter(typeof(Program)); 
     var con = Expression.Constant(5); 
     var prop = Expression.Property(param, typeof(Program).GetProperty("Value")); 
     var assign = Expression.Assign(prop, con); 
     Action<Program> lambda = Expression.Lambda<Action<Program>>(assign, param).Compile(); 

     Program p = new Program(); 
     lambda(p); 



     //p.Value = 5; 
    } 
} 

अब, अभिव्यक्ति पेड़ क्या करता है Main की अंतिम पंक्ति कहते हैं। एप्लिकेशन संकलित करें, फिर इसे परावर्तक में खोलें। आप आईएल कोड p.Value = 5; देख सकते हैं जो असाइनमेंट करता है। लेकिन अभिव्यक्ति पेड़ को रनटाइम पर बनाया और संकलित किया गया था। क्या संकलन से परिणामस्वरूप आईएल कोड देखना संभव है?

+0

तुम सिर्फ तुम * क्या कर रहे हैं * (अर्थात एक संपत्ति की स्थापना) के लिए आईएल * बराबर * करना चाहते हैं? या क्या 'अभिव्यक्ति' आउटपुट के बारे में कुछ है जिसे आप विशेष रूप से रुचि रखते हैं? –

+0

कुछ भी विशिष्ट नहीं है। मुझे समय-समय पर आईएल कोड देखना पसंद है। लेकिन अभिव्यक्तियों के साथ आप एक विधि बना सकते हैं जिसे संकलित असेंबली में कोई आईएल नहीं मिलता है। आईएल * उस * अभिव्यक्ति वृक्ष को बनाने के लिए प्रयोग किया जाता था, लेकिन अभिव्यक्ति वृक्ष के संकलन का नतीजा नहीं था। क्या इसका कोई मतलब है? यह केवल एक जिज्ञासा है और मैं देख सकता हूं कि किसी भी वास्तविक व्यावहारिक उद्देश्य की सेवा नहीं करता है। – Amy

+1

क्या आपने महान ** लिंककैड ** टूल के साथ प्रयास किया है? http://www.linqpad.net/ इसके साथ आप जेनरेट कोड को एमएसआईएल के रूप में प्रदर्शित कर सकते हैं और लगभग कुछ भी प्रयोग कर सकते हैं ... – AFract

उत्तर

28

हाँ! इस उपकरण का उपयोग:

http://blogs.msdn.com/b/haibo_luo/archive/2006/11/16/take-two-il-visualizer.aspx

यह अविश्वसनीय रूप से उपयोगी था जब मैं लागू करने गया था और संकलित डीबगिंग, के रूप में मुझे यकीन है कि आप कल्पना कर सकते हैं।

+3

एरिक, यदि आपके पास समय है, तो क्या आप इसे अधिक महत्वपूर्ण उत्तर में निकाल सकते हैं? केवल लिंक लिंक स्टैक ओवरफ़्लो पर निराश हैं। – casperOne

+0

बहुत बुरा यह संकलन योग्य नहीं है, क्या एक बाइनरी संस्करण उपलब्ध है? –

+2

@ कैस्परऑन: मैं आपको ऐसा करने के लिए प्रोत्साहित करता हूं। जोड़ने के लिए मेरे पास कुछ नहीं है। –

21

एक डायनामिकअस्प्लोर बनाएं, फिर एक डायनामिक मॉड्यूल, डायनामिक टाइप और डायनामिक मोड। उस विधि को सार्वजनिक और स्थैतिक बनाएं और इसे लैम्ब्डा पर विधि CompileTo() पर पास करें। जब आप असेंबली को सहेजते हैं तो इसे सहेजें। फिर सहेजें() विधि को कॉल करें और पथ पास करें। यह डिस्क पर लिखा जाएगा। इसे परावर्तक में खोलें।

कुछ की तरह:

var da = AppDomain.CurrentDomain.DefineDynamicAssembly(
    new AssemblyName("dyn"), // call it whatever you want 
    AssemblyBuilderAccess.Save); 

var dm = da.DefineDynamicModule("dyn_mod", "dyn.dll"); 
var dt = dm.DefineType("dyn_type"); 
var method = dt.DefineMethod(
    "Foo", 
    MethodAttributes.Public | MethodAttributes.Static); 

lambda.CompileToMethod(method); 
dt.CreateType(); 

da.Save("dyn.dll"); 
+0

यदि किसी भी 'DefineMethod' विधि से' MethodAttributes.Static' को हटाने में रुचि रखने वाले किसी भी मामले में, मुझे कुछ शोध हैं http://stackoverflow.com/a/3993023/903505 निष्कर्ष में, 'CompileToMethod' केवल स्थिर के साथ काम करता है तरीका – Ariex

संबंधित मुद्दे