के MethodInfo पुनर्प्राप्त करें मैं एक फ़ंक्शन लिखना चाहता हूं जो एक फ़ंक्शन को तर्क के रूप में लेता है और सिस्टम को वापस लौटाता है। Reflection.MethodInfo f से जुड़ा हुआ है।एक F # फ़ंक्शन
मुझे यकीन नहीं है कि यह संभव है या नहीं।
के MethodInfo पुनर्प्राप्त करें मैं एक फ़ंक्शन लिखना चाहता हूं जो एक फ़ंक्शन को तर्क के रूप में लेता है और सिस्टम को वापस लौटाता है। Reflection.MethodInfo f से जुड़ा हुआ है।एक F # फ़ंक्शन
मुझे यकीन नहीं है कि यह संभव है या नहीं।
तो, मुझे अंततः एक समाधान मिला। बहुत हैकी, लेकिन हे! यह काम करता हैं! (संपादित करें: केवल डीबग मोड में)।
let Foo (f:S -> A[] -> B[] -> C[] -> D[] -> unit) =
let ty = f.GetType()
let argty = [|typeof<S>; typeof<A[]>; typeof<B[]>; typeof<C[]>;typeof<D[]>|]
let mi = ty.GetMethod("Invoke", argty)
let il = mi.GetMethodBody().GetILAsByteArray()
let offset = 9//mi.GetMethodBody().MaxStackSize
let token = System.BitConverter.ToInt32(il, offset)
let mb = ty.Module.ResolveMethod(token)
match Expr.TryGetReflectedDefinition mb with
| Some ex -> printfn "success %A" e
| None -> failwith "failed"
यह अच्छी तरह से काम करता है, भले ही एफ किसी अन्य असेंबली (.dll) में परिभाषित किया गया हो या वही जहां फू का कॉल होता है। यह अभी तक सामान्य नहीं है क्योंकि मुझे परिभाषित करना है कि क्या तर्क है, लेकिन मुझे यकीन है कि मैं ऐसा फ़ंक्शन लिख सकता हूं जो ऐसा करता है।
इस कोड को लिखने के बाद बाहर निकलता है कि डस्टिन के पास एक ही समस्या के समान समाधान है, हालांकि सी # में देखें (इसे here देखें)।
संपादित करें: तो यहाँ एक उपयोग उदाहरण है:
open System
open Microsoft.FSharp.Quotations
[<ReflectedDefinition>]
let F (sv:int) (a:int[]) (b:int[]) (c:int[]) (d:int[]) =
let temp = a.[2] + b.[3]
c.[0] <- temp
()
let Foo (f:S -> A[] -> B[] -> C[] -> D[] -> unit) =
let ty = f.GetType()
let arr = ty.BaseType.GetGenericArguments()
let argty = Array.init (arr.Length-1) (fun i -> arr.[i])
let mi = ty.GetMethod("Invoke", argty)
let il = mi.GetMethodBody().GetILAsByteArray()
let offset = 9
let token = System.BitConverter.ToInt32(il, offset)
let mb = ty.Module.ResolveMethod(token)
mb
let main() =
let mb = Foo F
printfn "%s" mb.Name
match Expr.TryGetReflectedDefinition mb with
| None ->()
| Some(e) -> printfn "%A" e
do main()
क्या यह एफ, और उसके एएसटी के नाम प्रिंट कर रहा है समारोह एक परिलक्षित परिभाषा है अगर करता है।
लेकिन आगे की जांच पड़ताल के बाद, यह होता है कि इस हैक केवल डिबग मोड में काम करता है (और एफ एक समारोह मूल्य के रूप में अच्छी तरह से एक शीर्ष स्तर परिभाषा के रूप में हो गया है), तो के रूप में अच्छी तरह से कह सकते हैं कि यह एक असंभव बात है करने के लिए।
डीबग मोड::
.method /*06000007*/ public strict virtual
instance class [FSharp.Core/*23000002*/]Microsoft.FSharp.Core.Unit/*01000006*/
Invoke(int32 sv,
int32[] a,
int32[] b,
int32[] c,
int32[] d) cil managed
// SIG: 20 05 12 19 08 1D 08 1D 08 1D 08 1D 08
{
// Method begins at RVA 0x21e4
// Code size 16 (0x10)
.maxstack 9
IL_0000: /* 00 | */ nop
IL_0001: /* 03 | */ ldarg.1
IL_0002: /* 04 | */ ldarg.2
IL_0003: /* 05 | */ ldarg.3
IL_0004: /* 0E | 04 */ ldarg.s c
IL_0006: /* 0E | 05 */ ldarg.s d
IL_0008: /* 28 | (06)000001 */ call void Program/*02000002*/::F(int32,
int32[],
int32[],
int32[],
int32[]) /* 06000001 */
IL_000d: /* 00 | */ nop
IL_000e: /* 14 | */ ldnull
IL_000f: /* 2A | */ ret
} // end of method [email protected]::Invoke
विज्ञप्ति मोड:
method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.Unit
Invoke(int32 sv,
int32[] a,
int32[] b,
int32[] c,
int32[] d) cil managed
{
// Code size 28 (0x1c)
.maxstack 7
.locals init ([0] int32 V_0)
IL_0000: nop
IL_0001: ldarg.2
IL_0002: ldc.i4.2
IL_0003: ldelem [mscorlib]System.Int32
IL_0008: ldarg.3
IL_0009: ldc.i4.3
IL_000a: ldelem [mscorlib]System.Int32
IL_000f: add
IL_0010: stloc.0
IL_0011: ldarg.s c
IL_0013: ldc.i4.0
IL_0014: ldloc.0
IL_0015: stelem [mscorlib]System.Int32
IL_001a: ldnull
IL_001b: ret
} // end of method [email protected]::Invoke
आप देख सकते हैं कि रिलीज में
यहाँ दोनों डिबग/रिलीज निर्माण में FSharpFunc के आह्वान विधि के आईएल कोड है मोड, कंपाइलर एफ के कोड को इनवॉक विधि में रेखांकित करता है, इसलिए कॉलिंग (और टोकन को पुनर्प्राप्त करने की संभावना) की जानकारी समाप्त हो गई है ..
यदि यह आपके लिए काम करता है, तो आप इसे उत्तर के रूप में स्वीकार करना चाहते हैं। – kersny
क्या आप एक उदाहरण उदाहरण दे सकते हैं? मैं समाधान के सामान्य विचार को समझता हूं, लेकिन मुझे नहीं लगता कि एफ के पास किस तरह का प्रकार है। –
यह (आसानी से) संभव नहीं है।
let printFunctionName f =
let mi = getMethodInfo f
printfn "%s" mi.Name
पैरामीटर 'एफ' बस प्रकार FSharpFunc < , का एक उदाहरण है>: नोट करने के लिए बात यह है कि जब आप लिखते हैं। तो निम्नलिखित सब संभव हो रहे हैं:
printFunctionName (fun x -> x + 1) // Lambda expression
printFunctionName String.ToUpper // Function value
printFunctionName (List.map id) // Curried function
printFunctionNAme (not >> List.empty) // Function composition
या तो मामले में इस
शायद यह मदद करता है, मुझे पता है कि f हमेशा एक फ़ंक्शन मान होता है। आप क्या सिफारिश करते हैं? मैं कोई हैक ले जाऊंगा .. – Stringer
करने के लिए कोई सीधा जवाब अगर वहाँ समारोह के किसी भी प्रकार के लिए एक सामान्य जवाब है मैं नहीं जानता कि वहाँ है, लेकिन अपने कार्य है अगर सरल ('एक ->' ख) तो आप लिख सकते हैं
let getMethodInfo (f : 'a -> 'b) = (FastFunc.ToConverter f).Method
धन्यवाद, मैंने कोशिश की है, लेकिन काम नहीं लग रहा है .. – Stringer
मदद नीचे कार्यक्रम करता है?
module Program
[<ReflectedDefinition>]
let F x =
x + 1
let Main() =
let x = F 4
let a = System.Reflection.Assembly.GetExecutingAssembly()
let modu = a.GetType("Program")
let methodInfo = modu.GetMethod("F")
let reflDefnOpt = Microsoft.FSharp.Quotations.Expr.TryGetReflectedDefinition(methodInfo)
match reflDefnOpt with
| None -> printfn "failed"
| Some(e) -> printfn "success %A" e
Main()
हाँ सही, बहुत कुछ, उम्मीद है कि मुझे विधि का नाम ("एफ") या मॉड्यूल नहीं पता है । – Stringer
आप MethodInfo के साथ क्या करना चाहते हैं? – Brian
मैं प्रतिबिंबित परिभाषा को erm के साथ प्राप्त करने का प्रयास करता हूं ..TryGetReflectedDefinition फ़ंक्शन का प्रयास करें। – Stringer
मुझे एफ # में कुछ भी पता नहीं है लेकिन ओ'कैम में आप प्री-प्रोसेसर का उपयोग कर ऐसा कर सकते हैं (मुझे नहीं पता कि एफ # में कुछ समान है या नहीं) http://groups.google.com/group/fa। caml/Browse_thread/thread/25c9706b89196140 – LB40