2012-03-23 10 views
7

मेरे पास एक situtaiton है जहां मैंने bussiness तर्क पढ़ा और वास्तविक मानों के साथ चर को प्रतिस्थापित करें और फिर मुझे परिणाम प्राप्त करने के लिए इसका मूल्यांकन करने की आवश्यकता है। मैं वर्तमान में यह करने के लिए bcParser का उपयोग कर रहा हूं और यह एक्सेल प्रारूप की तरह लिखे गए सभी तर्कों के लिए ठीक काम करता है।क्या बयान के गतिशील के लिए अभिव्यक्ति वृक्ष बनाना संभव है?

मुझ पर फेंक दिया गया वक्र गेंद यह है कि, यदि स्थिति if(cond, true, false) एक्सेल की तरह नहीं होगी, तो यह सी # की तरह होगी जहां if (cond) { true; } else { false;}, यह अधिक समझदार और बनाए रखने में आसान बनाता है। चूंकि मैं हाथ से पहले मूल्य के साथ सभी चर बदलता हूं, मुझे बस इसका मूल्यांकन करना है। वर्तमान में मैं सी # विधियों के तर्क को निर्यात करके और प्रतिबिंब का उपयोग करके इस समस्या को हल कर रहा हूं, मैं इसका मूल्यांकन कर रहा हूं और यह भी काम करता है।

मुझे आश्चर्य है कि कोई अन्य विकल्प है, मैं शर्त के लिए प्रत्येक कोड के लिए कोड लिखना नहीं चाहता हूं और रन टाइम पर इसका मूल्यांकन करना चाहता हूं। मैं सोच रहा था कि क्या मुझे किसी प्रकार का टोकन पार्सर बनाने में सक्षम होना चाहिए और सी # देशी अभिव्यक्ति evalution को कॉल करना चाहिए और गणना करना चाहिए। मैं विस्तार पेड़ों को समझने में नहीं गया हूं, ऐसा लगता है कि उस दृष्टिकोण के साथ यह संभव है। इससे पहले कि मैं वहां जाऊं, मैं जानना चाहूंगा कि यह संभव है? धन्यवाद,

+3

अभिव्यक्ति पेड़ आपको स्ट्रिंग को पार्स करने में मदद नहीं करेंगे। आप [कोडडॉम] (http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx) या [Rosalyn] (http://msdn.microsoft.com/en-us/roslyn] को देखना चाह सकते हैं)। –

उत्तर

5

हाँ!

कुंजी System.Linq.Expressions नामस्थान का उपयोग कर रही है। आप अपने कोड में या अपने पार्सर को संशोधित करके प्रोग्रामिंग रूप से अभिव्यक्ति वृक्ष का निर्माण कर सकते हैं, फिर इसे Delegate में संकलित करें। यह एपीआई आपके Delegate को DynamicAssembly के अंदर संकलित करता है जिसका अर्थ है कि आपके संकलित अभिव्यक्ति को कचरा कलेक्टर द्वारा स्मृति से अनलोड किया जा सकता है जब आप उन्हें पूरी तरह से अव्यवस्थित करते हैं।

True 
False 

कदम जहां अभिव्यक्ति एक लैम्ब्डा में संकलित किया गया है एक महत्वपूर्ण प्रदर्शन हिट हो सकता है, आप चाहते हैं जाएगा:

var b = true; 
Func<bool> condition =() => b; 
Action trueExpression =() => { Console.WriteLine(true); }; 
Action falseExpression =() => { Console.WriteLine(false); }; 

var e = Expression.Condition(
    Expression.Invoke(Expression.Constant(condition)), 
    Expression.Invoke(Expression.Constant(trueExpression)), 
    Expression.Invoke(Expression.Constant(falseExpression))); 

var λ = Expression.Lambda(e).Compile(); 

b = true; 
λ.DynamicInvoke(); 

b = false; 
λ.DynamicInvoke(); 

यह आउटपुट का उत्पादन:

यहाँ एक बहुत ही सरल उदाहरण है अपने संकलित lambdas के लिए एक कैशिंग रणनीति के साथ आने के लिए। हालांकि यह अच्छी तरह से लायक है, हालांकि डायनामिक इनवोक का उपयोग करके संकलित लैम्ब्डा को कॉल करना बहुत तेज़ है। लगभग उतना तेज़ जितना कि आपने इसे पहले संकलित किया था। यह तकनीक कोडडॉम कोड जनरेशन का उपयोग करने से काफी तेज है (जिसके लिए संकलन करने के लिए एक और प्रक्रिया की आवश्यकता होती है) और इसे उतारने योग्य असेंबली बनाने का प्रमुख लाभ है।

इस के लिए एकमात्र सीमा यह है कि आप इस एपीआई के साथ प्रकार नहीं बना सकते हैं। आपको स्वयं को अभिव्यक्तियों और बयानों तक सीमित करना होगा। हालांकि यह काफी शक्तिशाली है, यह डीएलआर की जादू की धड़कन है।

+1

आप लैम्ब्डा प्रतीक कैसे प्राप्त करते हैं? चाहते हैं! – usr

+1

पेस्ट कॉपी करें! यह सिर्फ एक यूनिकोड चरित्र है। सी # में वैध। –

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