2010-03-09 8 views
5

मुझे स्पष्ट याद आ रही है: मैं लैम्ब्डा अभिव्यक्ति अभिव्यक्ति वृक्ष के अंदर पैरामीटर के मान को कैसे एक्सेस करूं?एक अभिव्यक्ति वृक्ष में पैरामीटर एक्सप्रेशन का रन-टाइम मान प्राप्त करना

परिदृश्य: एक प्रतिनिधि के लिए मैं गतिशील रूप से एक अभिव्यक्ति वृक्ष निकाय के साथ एक लैम्ब्डा अभिव्यक्ति बना देता हूं जिसमें प्रतिनिधि x के समान हस्ताक्षर होते हैं। लैम्ब्बा के शरीर के अंदर, मैं कुछ सत्यापन, जांच, लॉगिंग सामान करता हूं (यह केवल परीक्षण कोड है, उत्पादन नहीं), और फिर मैं मूल पैरामीटर x मूल पैरामीटर के साथ आह्वान करता हूं। अगर प्रतिनिधि के पास वापसी मूल्य होता है, तो यह भी वापस आ जाता है।

यह काफी अच्छा काम करता है (मूल प्रतिनिधि को पैरामीटर पास करने सहित)।

लेकिन अगर मैं प्रतिनिधि/लैम्ब्डा को पास किए गए मूल पैरामीटर मानों तक पहुंचना चाहता हूं तो मैं ईंट की दीवार पर टक्कर मार रहा हूं।

छद्म कोड:

var del = new Func<string, int>(_=> {return 42;}); 
var paramDefs = Array.ConvertAll<ParameterInfo, ParameterExpression>(del.Method.GetParameters(), _ => { return Expression.Parameter(_.ParameterType, _.Name); }); 
var variableTest = Expression.Variable(typeof(string), "str"); 

var expression = Expression.Block(
    new [] { variableTest }, 
    // this line assigns the actual run time value (which is what I need) of the parameter to the variable - but I cannot hardcode the index. 
    //Expression.Assign(variableTest, paramDefs[0]) 
    // this line would assigns the ParameterExpression object (causing a run-time exception since the type of the variable is string) ... I need the _value_ of the first (or nth) parameter. 
    Expression.Assign(variableTest, Expression.ArrayIndex(Expression.Constant(paramDefs), Expression.Constant(0))) 
); 
var lamdba = Expression.Lambda(del.GetType(), expression, "foo", paramDefs); 
var del2 = lamdba.Compile() as Func<string, int>; 
del2("this is a test"); 
+0

टिप्पणी-आउट कोड सही प्रतीत होता है, इसलिए मैं ऐसा करूँगा। आप कहते हैं कि आप इंडेक्स को हार्ड-कोड नहीं कर सकते हैं। क्यों नहीं? मुझे लगता है कि यह ठीक काम करेगा। –

+0

मैंने तब से कोड बदल दिया है। मैं शुरुआत में अभिव्यक्ति वृक्ष (अभिव्यक्ति.लूप) में paramDefs पर लूप करना चाहता था, प्रत्येक पैरामीटर को एक-एक करके जाकर। चूंकि कोड किसी भी प्रतिनिधि प्रकार पर काम करता है, इसलिए इंडेक्स हार्ड कोडिंग काम नहीं कर सका। मैंने अभिव्यक्ति वृक्ष से लूपिंग निर्माण खींचा। 5 पैरामीटर वाले प्रतिनिधि के लिए, अब मैं केवल पांच अभिव्यक्ति उत्पन्न करता हूं (सबसे सरल मामला प्रत्येक पैरामीटर मान को किसी ऑब्जेक्ट में कॉपी कर रहा है [])। हालांकि, प्रारंभिक प्रश्न अभी भी मुझे खराब करता है - क्या पैरामीटर एक्स्प्रेशन उदाहरण से वास्तविक मान प्राप्त करने का कोई तरीका है? – dalo

उत्तर

3

ऐसा लगता है कि अभिव्यक्ति के पेड़ संकलक बहुत ज्यादा भ्रमित (अच्छी तरह से, मैं इस कोड से भी उलझन में था)। मैं देख सकता हूं कि आपने क्या करने की कोशिश की: आपको एक सरणी से तत्व मिला, फिर आपने सरणी पर लूप करने का निर्णय लिया। लेकिन आप सरणी [पैरामीटर एक्स्प्रेशन] नहीं कर सका, इसलिए आपने ऐरेइंडेक्स का उपयोग किया। लेकिन ...

लेकिन वास्तव में ऐरेइंडेक्स "स्ट्रिंग" नहीं लौटाता है। यह MethodCallExpression देता है। तो, इस "असाइन करें" अभिव्यक्ति में आपके पास वास्तव में पैरामीटर एक्स्प्रेशन और MethodCallExpression है। ईटी कंपाइलर इन अभिव्यक्तियों को संकलित करने के लिए पर्याप्त स्मार्ट है और परिणामों को असाइन करने का प्रयास करता है। लेकिन आपके MethodCallExpression का परिणाम पैरामीटर एक्स्प्रेशन है। जब आपके पास paramDefs था [0], तो आपके पास पैरामीटर एक्स्प्रेशन तुरंत था और संकलक इसे संभाल सकता था। लेकिन नेस्टेड अभिव्यक्तियों को संकलित करना कठिन है और यह पूरी तरह अस्पष्ट है कि आप वास्तव में इस नेस्टेड अभिव्यक्ति को संकलित करना चाहते हैं या नहीं।

आप क्या कर सकते हैं विधिCallExpression को संकलित और आह्वान करना है, इसलिए आपके पास असाइन अभिव्यक्ति में पैरामीटर एक्स्प्रेशन होगा (जैसा कि आपने पहले किया था)। वह ऐसा दिखाई हो सकता है:

// Replace Assign in your Block expression. 
Expression.Assign(variableTest, Expression.Lambda<Func<ParameterExpression>>(Expression.ArrayIndex(Expression.Constant(paramDefs), Expression.Constant(0))).Compile()()), 

लेकिन यह प्रदर्शन के संदर्भ (प्लस कोड बदसूरत है) में बहुत भारी हो सकता है। तो, मैं अभिव्यक्ति के पेड़ से लूप खींचने के आपके विचार से चिपके रहूंगा।

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