F# 如何获取[<;ReflectedDefinition>;]标记模块中函数的AST?
问题在于实际获取模块的类型。为了做到这一点,菲利普·特里福德给出了一个很好的答案: 基本上,向模块添加一个helper值,该值返回该模块的类型:F# 如何获取[<;ReflectedDefinition>;]标记模块中函数的AST?,f#,F#,问题在于实际获取模块的类型。为了做到这一点,菲利普·特里福德给出了一个很好的答案: 基本上,向模块添加一个helper值,该值返回该模块的类型: open Microsoft.FSharp.Quotations open Microsoft.FSharp.Quotations.DerivedPatterns open Microsoft.FSharp.Reflection open System.Reflection 然后,我可以打印结果,例如: [|“get_fooType:Some Pro
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.DerivedPatterns
open Microsoft.FSharp.Reflection
open System.Reflection
然后,我可以打印结果,例如:
[|“get_fooType:Some PropertyGet(Some(Call(None,TypeOf,[])),DeclaringType,[])”;
“get_x:Some Value(5)”;
y:一些Lambda(unitVar0,值(6));
“z:一些Lambda(a,a)”|]
对于用例,当反射的定义位于另一个程序集中(例如F#dll)时,可以不使用标记接口技巧,如下所示:
let foo_members =
Foo.fooType.GetMethods()
|> Array.filter (fun mi -> match mi with | MethodWithReflectedDefinition x -> true | _ -> false)
|> Array.map (fun m -> sprintf "%s: %A" (m.Name) (Expr.TryGetReflectedDefinition(m :> MethodBase) ) )
开放系统
打开Microsoft.FSharp.quotes
打开Microsoft.FSharp.Quotences.DerivedPatterns
打开Microsoft.FSharp.Reflection
开放系统。反射
打开FSharp.Reflection.FSharpReflectionExtensions
让tryGetReflectedModules(a:组件):seq=
a、 定义类型
|>顺序过滤器
(乐趣dt->
自定义属性
|>Seq.map(有趣的cad->cad.AttributeType)
|>Seq.filter((=)(typeof))
|>我是空的
|>不是
)
让astFromReflectedDefinition(mi:MethodInfo):Expr选项=
mi:>MethodBase |>Expr.TryGetReflectedDefinition
让reflectedMethodsOfAModule(m:System.Type):(MethodInfo*Expr)[]=
m、 GetMethods()
|>Array.map(乐趣m->(m,astFromReflectedDefinition m))
|>Array.filter(snd>>Option.isSome)
|>Array.map(fun(x,y)->(x,Option.get y))
let reflectAssembly(assemblyPath:string)=
设a=System.Reflection.Assembly.LoadFile(assemblyPath)
A.
|>TRYGETREFLECTED模块
|>Seq.map(fun x->(x,reflectedMethodsOfAModule(x.AsType()))
其中,例如,我用于测试上述代码的程序集如下所示:
open System
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.DerivedPatterns
open Microsoft.FSharp.Reflection
open System.Reflection
open FSharp.Reflection.FSharpReflectionExtensions
let tryGetReflectedModules (a : Assembly) : seq<TypeInfo> =
a.DefinedTypes
|> Seq.filter
(fun dt ->
dt.CustomAttributes
|> Seq.map (fun cad -> cad.AttributeType)
|> Seq.filter ((=) (typeof<ReflectedDefinitionAttribute>))
|> Seq.isEmpty
|> not
)
let astFromReflectedDefinition (mi : MethodInfo) : Expr option =
mi :> MethodBase |> Expr.TryGetReflectedDefinition
let reflectedMethodsOfAModule (m : System.Type) : (MethodInfo * Expr) [] =
m.GetMethods()
|> Array.map (fun m -> (m,astFromReflectedDefinition m))
|> Array.filter (snd >> Option.isSome)
|> Array.map (fun (x,y) -> (x, Option.get y))
let reflectAssembly (assemblyPath : string) =
let a = System.Reflection.Assembly.LoadFile(assemblyPath)
a
|> tryGetReflectedModules
|> Seq.map (fun x -> (x,reflectedMethodsOfAModule (x.AsType())))
名称空间输入
[]
模块Api=
让跟踪s=
对于[0..3]中的uu,执行System.Diagnostics.Trace.WriteLine s
[]
模块Foo=
让foobar(x:string):string=
x、 托珀()
您可以在程序集中获得顶级类型,它们恰好是(静态)类,表示Fsharp程序集的模块,并测试
ReflectedDefinitionAttribute
的存在。然后,你从那里开始。我看到了这个问题。我使用GetModuleType
helper函数尝试了这个答案。我尝试了交互式,但没有成功。我认为你的答案大致相同。有没有一种方法不使用powerpack(现在应该已经过时了)并且在interactive中也可以使用?还有,哪一个在不向模块添加标签或类似内容的情况下工作?我记得我在其他论坛上问过这件事,但一直没有得到答案。为什么没有类似的Microsoft.FSharp.Reflection.Module.GetType()
呢?@BitTickler这只是这个问题的第一个答案,需要powerpack。我在那里发布的示例代码在interactive中工作得很好。事实上-只是复制了一下,它就工作了!好吧,我将把它作为一个解决办法,直到一些微软的家伙决定应该有一个简单的方法来做到这一点!谢谢你@BitTickler我快速浏览了F#语言设计用户语音网站,似乎之前没有提到过,是否值得在那里列出?我在思考如何对需要不同语言协作的应用程序进行(元)编程时偶然发现了这一点。示例:SecondLife脚本语言和http,以及一些SecondLife基于AJAX的HUD的脚本。或者:一些websocket html应用程序的f#后端。更为深奥的是:在F#中编程C,在F#中测试它,然后从中生成代码,希望有更少的bug。每当我想到这些事情,我都会偶然发现如何在模块上使用[]的问题。角落案例还是对公众有用?你决定;)
[<ReflectedDefinition>]
module Foo =
type internal IMarker = interface end
let fooType = typeof<IMarker>.DeclaringType
let x = 5
let y () = 6
let z a = a
let foo_members =
Foo.fooType.GetMethods()
|> Array.filter (fun mi -> match mi with | MethodWithReflectedDefinition x -> true | _ -> false)
|> Array.map (fun m -> sprintf "%s: %A" (m.Name) (Expr.TryGetReflectedDefinition(m :> MethodBase) ) )
open System
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.DerivedPatterns
open Microsoft.FSharp.Reflection
open System.Reflection
open FSharp.Reflection.FSharpReflectionExtensions
let tryGetReflectedModules (a : Assembly) : seq<TypeInfo> =
a.DefinedTypes
|> Seq.filter
(fun dt ->
dt.CustomAttributes
|> Seq.map (fun cad -> cad.AttributeType)
|> Seq.filter ((=) (typeof<ReflectedDefinitionAttribute>))
|> Seq.isEmpty
|> not
)
let astFromReflectedDefinition (mi : MethodInfo) : Expr option =
mi :> MethodBase |> Expr.TryGetReflectedDefinition
let reflectedMethodsOfAModule (m : System.Type) : (MethodInfo * Expr) [] =
m.GetMethods()
|> Array.map (fun m -> (m,astFromReflectedDefinition m))
|> Array.filter (snd >> Option.isSome)
|> Array.map (fun (x,y) -> (x, Option.get y))
let reflectAssembly (assemblyPath : string) =
let a = System.Reflection.Assembly.LoadFile(assemblyPath)
a
|> tryGetReflectedModules
|> Seq.map (fun x -> (x,reflectedMethodsOfAModule (x.AsType())))
namespace Input
[<ReflectedDefinition>]
module Api =
let trace s =
for _ in [0..3] do System.Diagnostics.Trace.WriteLine s
[<ReflectedDefinition>]
module Foo =
let foobar (x : string) : string =
x.ToUpper()