按属性和类型反映模块中的 let 绑定
Reflecting let bindings in a module by attribute and type
我试图在整个给定程序集中查找具有特定属性和类型的 let 绑定。
例如,以下类型和属性:
type TargetType = { somedata: string }
type MarkingAttribute() = inherit System.Attribute()
那么我想在以下模块中查找值:
module SomeModule =
[<Marking>]
let valueIWantToFind = {somedata = "yoyo"}
所以我正在寻找的是具有以下签名的函数(假设它适用于通用函数签名):
let valuesOfTypeWithAttribute<'t,'attr> (assembly: Assembly) : 't list = ...
我的徒劳尝试似乎因缺乏对 F# 模块如何转换为 CLR(CLI?)的理解而受阻类。
我有以下 FSI 片段,不幸的是没有找到:
open System.Reflection
let types = Assembly.GetExecutingAssembly().GetTypes()
let fiWithAttribute (attributeType: System.Type) (fi: FieldInfo) =
fi.CustomAttributes
|> Seq.exists (fun attr -> attr.AttributeType = attributeType)
let fields =
types
|> Array.collect (fun t -> t.GetFields())
|> Array.filter (fiWithAttribute typeof<MarkingAttribute>)
任何帮助或指点将不胜感激。
模块被编译为 类 静态成员。将程序集加载到一个名为 assembly
的值中,然后开始调查:
> let publicTypes = assembly.GetExportedTypes ();;
val publicTypes : System.Type [] =
[|Ploeh.Whosebug.Q36245870.TargetType;
Ploeh.Whosebug.Q36245870.MarkingAttribute;
Ploeh.Whosebug.Q36245870.SomeModule|]
如您所知,SomeModule
是以下类型之一:
> let someModule =
publicTypes |> Array.find (fun t -> t.Name.EndsWith "SomeModule");;
val someModule : System.Type = Ploeh.Whosebug.Q36245870.SomeModule
您现在可以获得以下类型的所有成员:
> let members = someModule.GetMembers ();;
val members : MemberInfo [] =
[|Ploeh.Whosebug.Q36245870.TargetType get_valueIWantToFind();
System.String ToString(); Boolean Equals(System.Object);
Int32 GetHashCode(); System.Type GetType();
Ploeh.Whosebug.Q36245870.TargetType valueIWantToFind|]
这个数组包含 let-bound 函数 valueIWantToFind
,它具有所需的属性:
> let attrs = members.[5].GetCustomAttributes ();;
val attrs : System.Collections.Generic.IEnumerable<System.Attribute> =
[|Ploeh.Whosebug.Q36245870.MarkingAttribute;
Microsoft.FSharp.Core.CompilationMappingAttribute|]
马克的回应让我走上了成功之路。反射不适用于完全在 FSI 中定义的模块(至少在我的设置中不适用于我)。
我想出的函数是这样的:
open Microsoft.FSharp.Reflection
let letBindingsWithTypeAndAttribute<'t,'attr> (assembly: Assembly) : 't array =
let publicTypes = assembly.GetExportedTypes ()
let modules = publicTypes |> Array.filter FSharpType.IsModule
let members = modules |> Array.collect (fun m -> m.GetMembers ())
let miHasAttribute (mi : MemberInfo) =
mi.GetCustomAttributes ()
|> Seq.exists (fun attr' -> attr'.GetType() = typeof<'attr>)
let withAttr =
members
|> Array.filter miHasAttribute
let valueOfBinding (mi : MemberInfo) =
let property = mi.Name
mi.DeclaringType.GetProperty(property).GetValue null
withAttr
|> Array.map valueOfBinding
|> Array.choose (fun o -> match o with
| :? 't as x -> Some x
| _ -> None)
我试图在整个给定程序集中查找具有特定属性和类型的 let 绑定。
例如,以下类型和属性:
type TargetType = { somedata: string }
type MarkingAttribute() = inherit System.Attribute()
那么我想在以下模块中查找值:
module SomeModule =
[<Marking>]
let valueIWantToFind = {somedata = "yoyo"}
所以我正在寻找的是具有以下签名的函数(假设它适用于通用函数签名):
let valuesOfTypeWithAttribute<'t,'attr> (assembly: Assembly) : 't list = ...
我的徒劳尝试似乎因缺乏对 F# 模块如何转换为 CLR(CLI?)的理解而受阻类。
我有以下 FSI 片段,不幸的是没有找到:
open System.Reflection
let types = Assembly.GetExecutingAssembly().GetTypes()
let fiWithAttribute (attributeType: System.Type) (fi: FieldInfo) =
fi.CustomAttributes
|> Seq.exists (fun attr -> attr.AttributeType = attributeType)
let fields =
types
|> Array.collect (fun t -> t.GetFields())
|> Array.filter (fiWithAttribute typeof<MarkingAttribute>)
任何帮助或指点将不胜感激。
模块被编译为 类 静态成员。将程序集加载到一个名为 assembly
的值中,然后开始调查:
> let publicTypes = assembly.GetExportedTypes ();;
val publicTypes : System.Type [] =
[|Ploeh.Whosebug.Q36245870.TargetType;
Ploeh.Whosebug.Q36245870.MarkingAttribute;
Ploeh.Whosebug.Q36245870.SomeModule|]
如您所知,SomeModule
是以下类型之一:
> let someModule =
publicTypes |> Array.find (fun t -> t.Name.EndsWith "SomeModule");;
val someModule : System.Type = Ploeh.Whosebug.Q36245870.SomeModule
您现在可以获得以下类型的所有成员:
> let members = someModule.GetMembers ();;
val members : MemberInfo [] =
[|Ploeh.Whosebug.Q36245870.TargetType get_valueIWantToFind();
System.String ToString(); Boolean Equals(System.Object);
Int32 GetHashCode(); System.Type GetType();
Ploeh.Whosebug.Q36245870.TargetType valueIWantToFind|]
这个数组包含 let-bound 函数 valueIWantToFind
,它具有所需的属性:
> let attrs = members.[5].GetCustomAttributes ();;
val attrs : System.Collections.Generic.IEnumerable<System.Attribute> =
[|Ploeh.Whosebug.Q36245870.MarkingAttribute;
Microsoft.FSharp.Core.CompilationMappingAttribute|]
马克的回应让我走上了成功之路。反射不适用于完全在 FSI 中定义的模块(至少在我的设置中不适用于我)。
我想出的函数是这样的:
open Microsoft.FSharp.Reflection
let letBindingsWithTypeAndAttribute<'t,'attr> (assembly: Assembly) : 't array =
let publicTypes = assembly.GetExportedTypes ()
let modules = publicTypes |> Array.filter FSharpType.IsModule
let members = modules |> Array.collect (fun m -> m.GetMembers ())
let miHasAttribute (mi : MemberInfo) =
mi.GetCustomAttributes ()
|> Seq.exists (fun attr' -> attr'.GetType() = typeof<'attr>)
let withAttr =
members
|> Array.filter miHasAttribute
let valueOfBinding (mi : MemberInfo) =
let property = mi.Name
mi.DeclaringType.GetProperty(property).GetValue null
withAttr
|> Array.map valueOfBinding
|> Array.choose (fun o -> match o with
| :? 't as x -> Some x
| _ -> None)