如何获取接口实例方法的F#报价?

如何获取接口实例方法的F#报价?,f#,quotations,F#,Quotations,在F#中,我们可以通过对象表达式创建接口实例,但是当我尝试在instance方法上使用attributeReflectedDefinition时,我无法获得引用。方法信息在接口类型中声明,而不是在实例类型中声明 以下是我的测试代码: module Test open System open System.Reflection open Microsoft.FSharp.Quotations open Microsoft.FSharp.Quotations.Patterns open Micro

在F#中,我们可以通过对象表达式创建接口实例,但是当我尝试在instance方法上使用attribute
ReflectedDefinition
时,我无法获得引用。方法信息在接口类型中声明,而不是在实例类型中声明

以下是我的测试代码:

module Test

open System
open System.Reflection
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
open Microsoft.FSharp.Quotations.DerivedPatterns
open Microsoft.FSharp.Quotations.ExprShape

type IMyInterface =
    abstract Foo : int -> int

let createMyInterface () =
    { new IMyInterface with
        [<ReflectedDefinition>]
        member this.Foo a = a + 1 }

let expr =
    let a = createMyInterface()
    <@ a.Foo(42) @>

let rec iterExpr (expr:Expr) =
    match expr with
    | Call(objectExpr, info, paramExprs) ->
        printfn "info: %A" info
        printfn "reflected type: %A" info.ReflectedType
        match info with
        | MethodWithReflectedDefinition methodExpr ->
            printfn "%A" methodExpr
        | _ -> failwith "No reflected definition"

    | ShapeVar _ -> failwithf "TODO: %A" expr
    | ShapeLambda _ -> failwithf "TODO: %A" expr
    | ShapeCombination _ -> failwithf "TODO: %A" expr

let test() =
    iterExpr expr

[<EntryPoint>]
let main argv = 
    test()
    0 // return an integer exit code
我还使用dotPeek检查了生成的程序集,它是作为派生类实现的:

[编译映射(SourceConstructFlags.ObjectType)]
[可序列化]
公共接口IMyInterface
{
int Foo([In]int obj0);
}
[编译映射(SourceConstructFlags.Closure)]
[可序列化]
[特殊名称]
[StructLayout(LayoutKind.Auto,CharSet=CharSet.Auto)]
内部密封类createMyInterface\u004014:Test.IMyInterface
{
公共createMyInterface\u004014()
{
基本参数。\u002Ector();
Test.createMyInterface\u004014 createMyInterface14=this;
}
[反射定义]
int Test.IMyInterface.Test\u002dimynterface\u002DFoo([In]int obj0)
{
返回obj0+1;
}
}

所以,问题是,当我在引号中调用
Foo
方法时,调用模式get
MethodInfo
,它在接口类型中声明,没有定义。那么,我如何才能得到真正的实现
MethodInfo
?然后我可以得到实施的报价?

简而言之,这是您的问题:

  • 您正在通过定义方法的类型的实例调用虚拟方法
  • 您希望引号包含对派生类上定义的方法的调用
  • 这将不起作用,并且不仅限于接口或对象表达式:

    type A() = 
        abstract M : unit -> unit
        default this.M() = printfn "abstract"
    
    type T() =
        inherit A() with
            [<ReflectedDefinition>]
            override this.M() = printfn "override"
    
    let expr =
        let a : A = upcast T()
        <@ a.M() @>
    
    type A()=
    摘要M:单位->单位
    默认值this.M()=printfn“abstract”
    类型T()=
    继承带有
    []
    重写此.M()=printfn“重写”
    让我们来解释一下=
    设a:a=上抛T()
    

    从根本上说,对象表达式的全部要点是提供非密封类的匿名实现,因此您所要求的对我来说没有意义-编译器只知道对象是实现该接口的某个实例,但不知道该实例的具体类型,因此不知道是哪个实例(可能有很多)要使用的具体方法。

    谢谢,是的,我知道,这是一个虚拟函数。但虚拟函数必须有一种方法来定位其具体实现,否则无法执行。我想知道的是,我想知道一种方法,通过给定虚拟函数的方法信息来定位具体实现,但不是执行它,我需要获取它使用案例是,我尝试在Quotence中使用此功能来编写GPU代码,我不想执行虚拟函数,但希望获取Quote并基于它生成GPU代码。您知道如何做到这一点吗?不,创建Quote时,F#编译器无法知道运行时类型(报价单是根据其中包含的语法树创建的,它独立于运行时值)。你可以在运行时做一些骇客的事情来让它工作,但似乎接口是做你想做的事情的错误方式-为什么不使用非虚拟方法呢?非虚拟方法没有问题,对象表达式是一种很好的方式。是的,我同意你的看法,引号在编译时,它对运行时的东西没有概念。一个d我想了一会儿,我意识到我可能需要在调用模式中检查objectExpr中的某些内容,如果objectExpr是一个值,那么我可以得到它的运行时类型,它应该是具体的类型。谢谢你的回答!
    type A() = 
        abstract M : unit -> unit
        default this.M() = printfn "abstract"
    
    type T() =
        inherit A() with
            [<ReflectedDefinition>]
            override this.M() = printfn "override"
    
    let expr =
        let a : A = upcast T()
        <@ a.M() @>