2011-06-03 59 views
5

我认为我可以用引号来做到这一点 - 但我看不出如何。从f的名称作为字符串调用函数#

我是否应该只用一个函数表和他们的名字 - 或者他们是这样做的一种方式?

谢谢。

欲了解更多信息......

我从Excel中调用了大量的F#功能,我不知道如果我能写AF#功能

让fs_wrapper无(f_name:字符串)( f_params:列表中双击)= 此位调用FNAME与f_params

然后用

= fs_wrapper无( “my_func,并将”,3.14,2.71)

而不是单独包装所有功能。

+1

你可以更多地展示你想要做的事情吗? – Daniel 2011-06-03 22:00:55

回答

9

您将需要使用标准的.NET反射来执行此操作。引用不会有帮助,因为它们使用标准的.NET MethodInfo表示函数调用,因此无论如何您都需要使用反射。引用的唯一好处(与天真的反射相比)是,你可以编译它们,这可以给你更好的表现(但编译并不完美)。

根据您的具体情况(如哪里的功能定位),你必须这样做:

module Functions = 
    let sin x = sin(x) 
    let sqrt y = sqrt(y) 

open System.Reflection 

let moduleInfo = 
    Assembly.GetExecutingAssembly().GetTypes() 
    |> Seq.find (fun t -> t.Name = "Functions") 

let name = "sin" 
moduleInfo.GetMethod(name).Invoke(null, [| box 3.1415 |]) 

除非你需要一些可扩展性还是有大量的功能,使用字典包含字符串作为键和功能价值作为价值可能是更容易的选择:

let funcs = 
    dict [ "sin", Functions.sin; 
     "sqrt", Functions.sqrt ] 

funcs.[name](3.1415) 
+0

谢谢,这个效果很好。我也可以将模块名称作为字符串传递。接下来的事情是参数类型管理,但我会离开这一段时间。什么是'盒子'? – b1g3ar5 2011-06-03 23:27:49

+0

@ b1g3ar5 - Invoke方法将参数作为对象数组('obj []'),因为它无法知道实际的参数类型。 'box'操作将'float'值运行为'obj'值。 '[|的类型3.14 |]'会是'float []',它不符合预期的类型。 – 2011-06-04 01:11:02

+0

所有这些语法上的错误都让我错过了Python/Ruby。即使C#与动态,如果你有。 – GregC 2011-06-04 03:42:06

2

有很多种方法,但一个方法是使用反射,例如:

typeof<int>.GetMethod("ToString", System.Type.EmptyTypes).Invoke(1, null) 
typeof<int>.GetMethod("Parse", [|typeof<string>|]).Invoke(null, [|"112"|]) 

GetMethod可选地接受一个定义签名的类型数组,但是如果你的方法是明确的,你可以跳过。

相关问题