如何获取接口实例方法的F#报价?
在F#中,我们可以通过对象表达式创建接口实例,但是当我尝试在instance方法上使用attribute如何获取接口实例方法的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
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
方法时,调用模式getMethodInfo
,它在接口类型中声明,没有定义。那么,我如何才能得到真正的实现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() @>