F# 按属性和类型反映模块中的let绑定
我试图在给定的程序集中找到具有特定属性和类型的let绑定 例如,以下类型和属性:F# 按属性和类型反映模块中的let绑定,f#,system.reflection,F#,System.reflection,我试图在给定的程序集中找到具有特定属性和类型的let绑定 例如,以下类型和属性: type TargetType = { somedata: string } type MarkingAttribute() = inherit System.Attribute() > let attrs = members.[5].GetCustomAttributes ();; val attrs : System.Collections.Generic.IEnumerable<System.
type TargetType = { somedata: string }
type MarkingAttribute() = inherit System.Attribute()
> let attrs = members.[5].GetCustomAttributes ();;
val attrs : System.Collections.Generic.IEnumerable<System.Attribute> =
[|Ploeh.StackOverflow.Q36245870.MarkingAttribute;
Microsoft.FSharp.Core.CompilationMappingAttribute|]
然后,我想在以下模块中找到该值:
module SomeModule =
[<Marking>]
let valueIWantToFind = {somedata = "yoyo"}
modulesomemodule=
[]
让valueIWantToFind={somedata=“yoyo”}
因此,我要寻找的是一个具有以下签名的函数(假设它适合于泛型函数签名):
让valuesOfTypeWithAttribute(程序集:程序集):'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>)
开放系统。反射
让types=Assembly.getExecutionGassembly().GetTypes()
let fiWithAttribute(attributeType:System.Type)(fi:FieldInfo)=
fi.CustomAttributes
|>Seq.exists(趣味属性->属性类型=属性类型)
设字段=
类型
|>Array.collect(fun t->t.GetFields())
|>Array.filter(fiWithAttribute类型)
非常感谢您的帮助或指点。模块被编译为具有静态成员的类。将程序集加载到名为
assembly
的值中,并开始调查:
> let publicTypes = assembly.GetExportedTypes ();;
val publicTypes : System.Type [] =
[|Ploeh.StackOverflow.Q36245870.TargetType;
Ploeh.StackOverflow.Q36245870.MarkingAttribute;
Ploeh.StackOverflow.Q36245870.SomeModule|]
正如您所知,SomeModule
是以下类型之一:
> let someModule =
publicTypes |> Array.find (fun t -> t.Name.EndsWith "SomeModule");;
val someModule : System.Type = Ploeh.StackOverflow.Q36245870.SomeModule
您现在可以获取该类型的所有成员:
> let members = someModule.GetMembers ();;
val members : MemberInfo [] =
[|Ploeh.StackOverflow.Q36245870.TargetType get_valueIWantToFind();
System.String ToString(); Boolean Equals(System.Object);
Int32 GetHashCode(); System.Type GetType();
Ploeh.StackOverflow.Q36245870.TargetType valueIWantToFind|]
此数组包括let绑定函数valueIWantToFind
,它具有所需的属性:
type TargetType = { somedata: string }
type MarkingAttribute() = inherit System.Attribute()
> let attrs = members.[5].GetCustomAttributes ();;
val attrs : System.Collections.Generic.IEnumerable<System.Attribute> =
[|Ploeh.StackOverflow.Q36245870.MarkingAttribute;
Microsoft.FSharp.Core.CompilationMappingAttribute|]
>让attrs=members[5].GetCustomAttributes();;
val属性:System.Collections.Generic.IEnumerable=
[| Ploeh.StackOverflow.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)
打开Microsoft.FSharp.Reflection
让letBindingsWithTypeAndAttribute(程序集:程序集):'t数组=
让publicTypes=assembly.GetExportedTypes()
让modules=publicTypes |>Array.filter FSharpType.IsModule
让members=modules |>Array.collect(fun m->m.GetMembers())
让miHasAttribute(mi:MemberInfo)=
mi.GetCustomAttributes()
|>Seq.exists(fun attr'->attr'.GetType()=某个x的类型
|(无)
使用GetMembers而不是GetFields-要了解如何翻译内容,请使用ILSpy。