मान लीजिए कि हम एक सरल एफ # उद्धरण करते हैं:जनरेट कर रहा है पैरामिट्रीकृत एफ # कोटेशन
type Pet = { Name : string } let exprNonGeneric = <@@ System.Func(fun (x : Pet) -> x.Name) @@>
जिसके परिणामस्वरूप उद्धरण की तरह है:
val exprNonGeneri : Expr = NewDelegate (System.Func`2[[FSI_0152+Pet, FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], x, PropertyGet (Some (x), System.String Name, []))
अब मैं इसे सामान्यीकरण करने के लिए चाहते हैं, इसलिए लिखने के बजाय मैं "पालतू पशु "और संपत्ति" नाम "मैं उस पर परिभाषित एक मनमाना प्रकार और विधि/संपत्ति का उपयोग कर सकता हूं। यहाँ है कि मैं क्या करने के लिए कोशिश कर रहा हूँ:
let exprGeneric<'T, 'R> f = <@@ System.Func<'T, 'R>(%f) @@> let exprSpecialized = exprGeneric<Pet, string> <@ (fun (x : Pet) -> x.Name) @>
जिसके परिणामस्वरूप अभिव्यक्ति अब अलग है:
val exprSpecialized : Expr = NewDelegate (System.Func`2[[FSI_0152+Pet, FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], delegateArg, Application (Lambda (x, PropertyGet (Some (x), System.String Name, [])), delegateArg))
आप देख सकते हैं, पहली और दूसरी अभिव्यक्ति के बीच अंतर यह है कि पहले मामले में शीर्ष स्तर NewDelegate अभिव्यक्ति में PropertyGet है, जबकि दूसरी अभिव्यक्ति एक आवेदन/Lambda अभिव्यक्ति में PropertyGet लपेटती है। और जब मैं इस अभिव्यक्ति को बाहरी कोड में पास करता हूं तो यह ऐसी अभिव्यक्ति संरचना की अपेक्षा नहीं करता है और विफल रहता है।
इसलिए मुझे उद्धरण के सामान्यीकृत संस्करण को बनाने के लिए कुछ तरीका चाहिए, इसलिए जब यह विशिष्ट हो जाए, तो परिणामी उद्धरण < @@ System.Func (मजेदार (x: पालतू) -> x.Name का सटीक मिलान है। @@ >। क्या यह संभव है? या यह केवल जेनरेट किए गए उद्धरण के लिए पैटर्न मिलान मैन्युअल रूप से लागू करने का विकल्प है और इसे मेरी आवश्यकता के अनुसार बदल सकता है?
अद्यतन। समाधान के लिए मैं निम्नलिखित एडाप्टर लागू किया:
let convertExpr (expr : Expr) = match expr with | NewDelegate(t, darg, appl) -> match (darg, appl) with | (delegateArg, appl) -> match appl with | Application(l, ldarg) -> match (l, ldarg) with | (Lambda(x, f), delegateArg) -> Expr.NewDelegate(t, [x], f) | _ -> expr | _ -> expr | _ -> expr
यह काम करता है - मैं अब 2 फार्म के लिए 1 से अभिव्यक्ति बदल सकते हैं। लेकिन मुझे यह जानने में दिलचस्पी है कि क्या इसे अभिव्यक्ति के पेड़ों के बिना, सरल तरीके से हासिल किया जा सकता है।
उत्तर और एक महान सुझाव के लिए धन्यवाद। हालांकि मैं अभी भी संबंधित मुद्दे से फंस गया हूं: क्या एक सामान्य एफ # प्रतिनिधि (जैसे मजेदार एक्स -> x.Name) को एक सामान्य उद्धरण में प्लग करना संभव है जो वास्तविक प्रकार से स्वतंत्र है, जैसे ऊपर उद्धरण # 2। यह मॉकिंग ढांचे के समान है: वे कंक्रीट इंटरफेस को जानने और कंक्रीट प्रकार इंजेक्ट किए बिना कुछ अभिव्यक्तियों को परिभाषित करते हैं। मैं इसे एफ # में प्राप्त करने में सक्षम नहीं प्रतीत होता। –
@ वाजिफ़ - मुझे यकीन नहीं है कि मैं आपका प्रश्न समझता हूं। क्या आप जो कुछ करने की कोशिश कर रहे हैं उस पर आप थोड़ा और विस्तार से जा सकते हैं? – kvb
मुझे एफ # और सी # के बीच इंटरऑप भेजने की जरूरत है। सी # एक निश्चित प्रकार की LINQ अभिव्यक्ति की अपेक्षा करता है। मैं इसे एफ # में हार्ड-कोडेड तरीके से लिख सकता हूं, लेकिन मैं इसके लिए एक सामान्य एफ # रैपर बनाना चाहता हूं। यह रैपर "मजेदार एक्स -> x.Name" जैसे इनपुट लैम्ब्डा के रूप में लेने में सक्षम होना चाहिए और उन्हें कोटेशन में परिवर्तित करना चाहिए। मुझे संदेह है कि सामान्य मामले में यह संभव नहीं है। –