2012-02-03 25 views
8

से, .Where एक अभिव्यक्ति> विधेय लेता है, जो मैं के रूप मेंअभिव्यक्ति <समारोह <T, bool>> एक एफ # समारोह LINQ में

<@ fun item:'a -> condition @> // Expr<'a -> bool> 

एफ # में लिखने मैं FSharp.Powerpack उपयोग कर रहा हूँ एक से अभिव्यक्ति का निर्माण कर सकते हैं उद्धरण, लेकिन यह मुझे क्या देता है एक विधिCallExpression है। गहरी लग रही है, पावरपैक कोड लैम्ब्डा को सही तरीके से बनाता है, लेकिन इसे कनवर्ट कॉल में लपेटता है (वह क्यों है?)। मुझे आश्चर्य है कि विधि कॉल (एक लैम्ब्डा) के लिए तर्क कास्टिंग करने के बाद अंत में मुझे अभिव्यक्ति मिल जाएगी> मुझे चाहिए।

तो प्रश्न यह है कि कनवर्ट कॉल, और वास्तव में फ़ंक हस्ताक्षर के साथ लैम्ब्डा कैसे प्राप्त करें।

+0

हे, किया आपको ऐसा करने का एक आसान तरीका मिल रहा है? – nicolas

+0

एक sidenote पर, यहां एक संबंधित प्रश्न है, (उद्धरण के साथ नहीं) http://stackoverflow.com/questions/3392000/interop-between-f-and-c-sharp-lambdas – nicolas

उत्तर

12

मुझे अपने सिर के शीर्ष को याद नहीं किया जा सकता है, जहां मुझे यह कोड मिला, लेकिन यह मैं Expr<'a -> 'b> से Expression<Func<'a, 'b>> को परिवर्तित करने के लिए उपयोग करता हूं। उम्मीद है कि यह आपकी समस्या का समाधान करेगा।

open System 
open System.Linq.Expressions 
open Microsoft.FSharp.Quotations 
open Microsoft.FSharp.Linq.QuotationEvaluation 

let toLinq (expr : Expr<'a -> 'b>) = 
    let linq = expr.ToLinqExpression() 
    let call = linq :?> MethodCallExpression 
    let lambda = call.Arguments.[0] :?> LambdaExpression 
    Expression.Lambda<Func<'a, 'b>>(lambda.Body, lambda.Parameters) 
+4

'expr.ToLinqExpression() 'अब' F # 'में 'माइक्रोसॉफ्ट.एफएसएचआरपी.लिंक। रनटाइम हेल्पर्स। लीफएक्सप्रेसियन कनवर्टर। क्वोटेशन टूएक्सप्रेस एक्सप्रप्र' – Maslow

4

एक तरीका यह है कि तुम अब यह कर सकते हैं तथ्य का लाभ लेने के लिए है कि एफ # जब नेट प्रकार है कि एक Expression<Func<...>> उम्मीद पर तरीकों लागू इस रूपांतरण स्वचालित रूप से प्रदर्शन करेंगे है।

मुझे पूरी तरह से यकीन नहीं है कि यह भाषा में जोड़ा गया है, लेकिन निश्चित रूप से F # 4 के साथ, आपको स्पष्ट रूप से FQ अभिव्यक्तियों को LINQ में परिवर्तित करने की आवश्यकता नहीं है। कारण आप पहली जगह में इस करना चाहता था IQueryable LINQ एपीआई (या अन्य अभिव्यक्ति आधारित नेट एपीआई) का उपयोग करने में सक्षम होना था तो यह अब सिर्फ किसी प्रयास के जैसे काम करता है,:

someEfDataContext.MyEntities.Single(fun e -> e.Id = 42) 

बस काम करता है। भले ही यह सामान्य लैम्ब्डा जैसा दिखता है (हमने एफ # की अभिव्यक्ति वाक्यविन्यास का उपयोग नहीं किया है), यह उस कोड को संकलित करता है जो एक एफ # अभिव्यक्ति ऑब्जेक्ट उत्पन्न करता है, और उसके बाद इसे LeafExpressionConverter‌​.QuotationToExpressi‌on पर ले जाता है ताकि इसे LINQ अभिव्यक्ति ऑब्जेक्ट में बदल दिया जा सके।

लेकिन कभी-कभी आप सीधे LINQ-style अभिव्यक्ति ऑब्जेक्ट को F # में पकड़ना चाहते हैं। (उदाहरण के लिए, कभी कभी यह उपयोगी एक एफ # समारोह है कि एक अभिव्यक्ति है कि आप एकाधिक प्रश्नों में इस्तेमाल करेंगे पैदा करता है लिखने के लिए है।) उस मामले में आप इस तरह एक सहायक लिख सकते हैं:

type FunAs() = 
    static member LinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e 

यह लगता है कि यह कुछ नहीं करता है - यह सिर्फ इसके तर्क देता है। हालांकि, क्योंकि FunAs एक .NET प्रकार है, F # स्वचालित रूप से किसी भी कॉल साइट को संकलित करेगा जो इसे fun अभिव्यक्ति के साथ कोड में अभिव्यक्त करता है जो उपयुक्त LINQ क्वेरी अभिव्यक्ति उत्पन्न करता है। उदा .:

let linqExpr = FunAs.LinqExpression(fun (e:MyEntity) -> e.Id = 42) 

यहाँ, linqExpr प्रकार Expression<Func<MyEntity, bool>> का हो जाएगा।

इसकी कुंजी यह है कि यह विधि .NET प्रकार का सदस्य है। आप एक साधारण एफ # समारोह के साथ सटीक एक ही बात का प्रयास करें:

let funAsLinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e 

जो यह की तरह लगता है FunAs.LinqExpression के रूप में बिल्कुल वही बात मतलब यह होना चाहिए, तो आप पाएंगे कि आप इसे उसी तरह से फोन नहीं कर सकते हैं। जैसे, आप की कोशिश करता है, तो यह:

let linqExpr = funAsLinqExpression(fun (e:MyEntity) -> e.Id = 42) 

आप एक (थोड़ा बेकार) त्रुटि मिलेगी: 'यह समारोह भी कई तर्क लेता है, या एक संदर्भ में, जहां एक समारोह expected` नहीं है में प्रयोग किया जाता है।

इस फ़ंक्शन को .NET प्रकार का सदस्य बनाकर, हम F # के सहायक का लाभ उठा सकते हैं "आप एक .NET API का आविष्कार कर रहे हैं जो LINQ-style अभिव्यक्ति की अपेक्षा करता है, मुझे आपके लिए इसका ख्याल रखने दें" सुविधा।

(यह वहाँ LINQ संकलक पूछ चित्र में एक .NET प्रकार लाए बिना आप के लिए यह एक ही चाल प्रदर्शन करने के लिए में से कुछ अधिक स्पष्ट तरीका है कि संभव है, लेकिन मैं इसे नहीं मिला है।)

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