寻找健壮,通用的op_Dynamic实现

Ste*_*sen 11 f#

我无法找到一个强大的,通用的op_Dynamic实现:任何人都可以指向我吗?到目前为止,搜索只出现了玩具或特定用途的实现,但我想有一个,比如说,比较强健性与C#的默认静态动态实现(即处理批次/所有情况,缓存反射调用)(它是我已经看过C#的静态动态了一段时间,所以请原谅我,如果我对它的能力的断言是错误的话.

谢谢!

jbt*_*ule 10

nuget上有一个FSharp.Interop.Dynamic模块,它应该使用dlr强大地处理动态运算符.

与许多片段相比,它有几个优点.

  • 性能它使用Dynamitey进行实现缓存的dlr调用,并且是.NET标准库
  • 处理返回void的方法,如果不丢弃那些结果,则会得到绑定异常.
  • dlr处理由函数自动调用委托返回的情况,这也允许你对FSharpFunc执行相同的操作
  • 添加!?前缀运算符,用于处理直接调用动态对象和在运行时没有类型的函数.

    它是开源的,Apache许可证,您可以查看实现,它包括单元测试示例案例.


Tom*_*cek 8

您永远无法完全实现?运算符.对于可能需要根据类型执行某些特殊操作的各种类型,可以对运算符实现不同的实现:

  • 因为Dictionary<T, R>,您希望它使用字典的查找功能
  • 对于您引用的文章中的SQL对象,您希望它使用特定的SQL API
  • 对于未知的.NET对象,您希望它使用.NET Reflection

如果您正在寻找使用Reflection的实现,那么您可以使用我在F#绑定中为MonoDevelop实现的实现(在GitHub上可用).它相当完整,处理属性访问,方法调用以及静态成员.(链接文件的其余部分大量使用它来调用F#编译器的内部成员).它直接使用Reflection,所以它很慢,但功能非常完整.

另一种方法是在.NET 4.0动态语言运行时之上实现运算符(这样它将使用与dynamicC#4中相同的底层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)
Run Code Online (Sandbox Code Playgroud)

这仅适用于具有单个参数的方法调用(您可以通过查看C#编译器为dynamic调用生成的代码来了解如何执行此操作).我想如果你把完整性(来自第一个)和使用DLR的方法混合在一起(在第二个中),你将获得最强大的实现.

编辑:我还将代码发布到F#Snippets.这是使用DLR的版本:http://fssnip.net/2U,这里是F#插件的版本(使用.NET Reflection):http://fssnip.net/2V