Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 按属性和类型反映模块中的let绑定_F#_System.reflection - Fatal编程技术网

F# 按属性和类型反映模块中的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.

我试图在给定的程序集中找到具有特定属性和类型的let绑定

例如,以下类型和属性:

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。