2010-05-17 7 views
9

आप अभिव्यक्ति के रूप में लैम्ब्डा का प्रतिनिधित्व करने के लिए Lambda Expression Objects का उपयोग कर सकते हैं।लैम्ब्डा अभिव्यक्तियों (और केवल रनटाइम पर ज्ञात एक प्रकार) का उपयोग करके जेनेरिक विधि को कॉल करना

आप एक सामान्य विधि कॉल का प्रतिनिधित्व करते हुए Lambda Expression Object कैसे बनाते हैं, यदि आप केवल सामान्य प्रकार के हस्ताक्षर के लिए उपयोग करते समय टाइप करते हैं- रनटाइम पर?

उदाहरण के लिए:

मैं एक Lambda Expression Objects कॉल करने के लिए बनाना चाहते हैं: public static TSource Last<TSource>(this IEnumerable<TSource> source)

लेकिन मैं केवल पता है कि TSource क्रम पर है।

+0

यह पूरी तरह से स्पष्ट नहीं है। आप किस ऑब्जेक्ट पर ऑब्जेक्ट बनाने की कोशिश कर रहे हैं? क्या आप लैम्बडा अभिव्यक्ति के साथ अंतिम जेनेरिक विधि का संदर्भ चाहते हैं? – casperOne

+0

@ कैस्परऑन: हाय कैस्पर! ए) मैं ** TheObject ** का एक उदाहरण बनाने की कोशिश कर रहा हूं, जो कि ** TheMethod ** के संदर्भ हैं। बी) हां, मैं लैम्ब्डा अभिव्यक्ति (लैम्ब्डा अभिव्यक्ति ऑब्जेक्ट का मतलब है) के साथ अंतिम विधि का संदर्भ देना चाहता हूं। धन्यवाद:) – SDReyes

उत्तर

20
static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() 
{ 
    var source = Expression.Parameter(
     typeof(IEnumerable<T>), "source"); 

    var call = Expression.Call(
     typeof(Enumerable), "Last", new Type[] { typeof(T) }, source); 

    return Expression.Lambda<Func<IEnumerable<T>, T>>(call, source) 
} 

या

static LambdaExpression CreateLambda(Type type) 
{ 
    var source = Expression.Parameter(
     typeof(IEnumerable<>).MakeGenericType(type), "source"); 

    var call = Expression.Call(
     typeof(Enumerable), "Last", new Type[] { type }, source); 

    return Expression.Lambda(call, source) 
} 
2

मैं पूरी तरह से सवाल समझ में नहीं आता है, लेकिन कोड है कि लिखा DTB बस के रूप में लिखा जा सकता है:

class MyUtils { 
    public static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() { 
    return source => source.Last(); 
    } 
} 

DTB द्वारा नमूने में कोड सी # कंपाइलर स्वचालित रूप से इस लैम्ब्डा अभिव्यक्ति से आपके लिए जेनरेट करता है (अभिव्यक्ति वृक्ष के रूप में संकलित, क्योंकि वापसी प्रकार Expression है) के समान ही है।

यदि आप रनटाइम पर टाइप जानते हैं, तो आप या तो डीटीबी द्वारा समाधान का उपयोग कर सकते हैं या आप प्रतिबिंब का उपयोग करके CreateLambda विधि (ऊपर) का आह्वान कर सकते हैं, जो धीमा हो सकता है, लेकिन आपको लैम्ब्डा में कोड लिखने की अनुमति देता है प्राकृतिक सी #:

var createMeth = typeof(MyUtils).GetMethod("CreateLambda"); 
LambdaExpression l = createMeth.MakeGenericMethod(yourType).Invoke(); 

इस विधि की अच्छी बात यह है कि CreateLambda में कोड और अधिक जटिल हो सकता है, जो स्पष्ट रूप से अभिव्यक्ति के पेड़ का उपयोग कर ऐसा करने के लिए वास्तव में मुश्किल होगा है।

+0

हाय टॉमस! मुझे अपने प्रोग्रामिंग संचार कौशल में सुधार करने की ज़रूरत है, मुझे पता है, मैं हाहाहा जानता हूं (लेकिन चिंता न करें मैं इस पर काम कर रहा हूं:)। मैंने वास्तव में क्या मतलब है इसका प्रतिनिधित्व करने के लिए प्रश्न को अद्यतन किया। अच्छा रिफैक्टर! +1 – SDReyes

+0

@SDReyes: "रनटाइम पर" महत्वपूर्ण बिंदु था। इसके बावजूद आप अभी भी अच्छे सी # वाक्यविन्यास का उपयोग कर सकते हैं (स्पष्ट रूप से अभिव्यक्ति पेड़ों का निर्माण किए बिना)। मेरा अद्यतन उत्तर देखें। –

+0

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

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