我无法找到一个强大的,通用的op_Dynamic实现:任何人都可以指向一个吗?到目前为止,搜索只出现了玩具或特定用途的实现,但我想有一个,比如说,比较强健性与C#的默认静态动态实现(即处理批次/所有情况,缓存反射调用)(它是我已经看过C#的静态动态了一段时间,所以请原谅我,如果我对它的能力的断言是错误的话。
谢谢!
答案 0 :(得分:9)
在nuget上有一个模块FSharp.Interop.Dynamic,它应该使用dlr强大地处理动态运算符。
与许多片段相比,它有几个优势。
添加!?前缀运算符,用于处理直接调用动态对象和在运行时没有类型的函数。
这是开源的Apache许可证,您可以查看implementation,其中包含单元测试example cases。
答案 1 :(得分:8)
您永远无法完全实现?
运算符。对于可能需要根据类型执行某些特殊操作的各种类型,可以以不同的方式实现运算符:
Dictionary<T, R>
,您希望它使用字典的查找功能如果您正在寻找使用Reflection的实现,那么您可以使用我在F#绑定中为MonoDevelop(available on GitHub)实现的实现。它相当完整,处理属性访问,方法调用以及静态成员。 (链接文件的其余部分大量使用它来调用F#编译器的内部成员)。它直接使用Reflection,因此速度很慢,但功能完备。
另一种替代方法是在.NET 4.0动态语言运行时之上实现运算符(以便它在C#4中使用与dynamic
相同的底层API)。我不认为在某处有一个实现,但这是一个简单的例子,你可以得到它:
#r "Microsoft.CSharp.dll"
open System
open System.Runtime.CompilerServices
open Microsoft.CSharp.RuntimeBinder
let (?) (inst:obj) name (arg:'T) : 'R =
// Create site (representing dynamic operation for converting result to 'R
let convertSite =
CallSite<Func<CallSite, Object, 'R>>.Create //'
(Binder.Convert(CSharpBinderFlags.None, typeof<'R>, null)) //'
// Create site for the method call with single argument of type 'T
let callSite =
CallSite<Func<CallSite, Object, 'T, Object>>.Create //'
(Binder.InvokeMember
( CSharpBinderFlags.None, name, null, null,
[| CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) |]))
// Run the method and perform conversion
convertSite.Target.Invoke
(convertSite, callSite.Target.Invoke(callSite, inst, arg))
let o = box (new Random())
let a : int = o?Next(10)
这仅适用于具有单个参数的方法调用(您可以通过查看C#编译器为dynamic
调用生成的代码来了解如何执行此操作)。我想如果你把完整性(从第一个)和使用DLR的方法混合在一起(在第二个方面),你将获得最强大的实现。
编辑:我还将代码发布到了F#Snippets。以下是使用DLR的版本:http://fssnip.net/2U,这是F#插件的版本(使用.NET Reflection):http://fssnip.net/2V