खोज…
एफ # कोटेशन का उपयोग कर प्रतिबिंब प्रतिबिंब
प्रतिबिंब उपयोगी है लेकिन नाजुक है। इस पर विचार करो:
let mi = typeof<System.String>.GetMethod "StartsWith"
इस तरह के कोड के साथ समस्याएं हैं:
- कोड काम नहीं करता है क्योंकि
String.StartsWith
कई ओवरलोड हैं - यहां तक कि अगर कोई भी अधिभार नहीं होगा अभी पुस्तकालय के बाद के संस्करणों में एक अधिभार जोड़ सकता है जिससे एक रनटाइम क्रैश हो सकता है
-
Rename methods
जैसे रिफ्लेक्टरिंग उपकरण प्रतिबिंब के साथ टूट जाते हैं।
इसका मतलब यह है कि हम कुछ समय के लिए एक रनटाइम क्रैश प्राप्त करते हैं जिसे संकलन-समय के रूप में जाना जाता है। जो कि सबॉप्टिमल लगता है।
F#
कोटेशन का उपयोग करके उपरोक्त सभी समस्याओं से बचना संभव है। हम कुछ सहायक कार्यों को परिभाषित करते हैं:
open FSharp.Quotations
open System.Reflection
let getConstructorInfo (e : Expr<'T>) : ConstructorInfo =
match e with
| Patterns.NewObject (ci, _) -> ci
| _ -> failwithf "Expression has the wrong shape, expected NewObject (_, _) instead got: %A" e
let getMethodInfo (e : Expr<'T>) : MethodInfo =
match e with
| Patterns.Call (_, mi, _) -> mi
| _ -> failwithf "Expression has the wrong shape, expected Call (_, _, _) instead got: %A" e
हम इस तरह के कार्यों का उपयोग करते हैं:
printfn "%A" <| getMethodInfo <@ "".StartsWith "" @>
printfn "%A" <| getMethodInfo <@ List.singleton 1 @>
printfn "%A" <| getConstructorInfo <@ System.String [||] @>
यह प्रिंट:
Boolean StartsWith(System.String)
Void .ctor(Char[])
Microsoft.FSharp.Collections.FSharpList`1[System.Int32] Singleton[Int32](Int32)
<@ ... @>
अर्थ है कि F#
अंदर अभिव्यक्ति को निष्पादित करने के बजाय अभिव्यक्ति का प्रतिनिधित्व करने वाला एक अभिव्यक्ति पेड़ उत्पन्न करता है। <@ "".StartsWith "" @>
एक अभिव्यक्ति ट्री बनाता है जो इस तरह दिखता है: Call (Some (Value ("")), StartsWith, [Value ("")])
। इस एक्सप्रेशन ट्री से मिलता है जो getMethodInfo
उम्मीद है और यह सही तरीके की जानकारी लौटाएगा।
यह ऊपर सूचीबद्ध सभी समस्याओं का समाधान करता है।