Ищете надежную, общую реализацию op_Dynamic
Я не смог найти надежную, общую реализацию op_Dynamic: кто-нибудь может указать мне одну? До сих пор в поисках использовались только игрушки или конкретные реализации, но я бы хотел иметь такую под рукой, которая, скажем, сравнивает по прочности со статической динамической реализацией C# по умолчанию (т. Е. Обрабатывает множество / все случаи, вызовы отражения кеша) (это Прошло много времени с тех пор, как я смотрел на статическую динамику в C#, так что извините, если мои утверждения о его возможностях неверны).
Спасибо!
2 ответа
В nuget есть модуль FSharp.Interop.Dynamic, который должен надежно обрабатывать динамический оператор с помощью dlr.
У этого есть несколько преимуществ перед многими фрагментами там.
- Производительность он использует Dynamitey для вызова dlr, который реализует кэширование и является стандартной библиотекой.NET
- Обрабатывая методы, которые возвращают void, вы получите обязательное исключение, если не откажетесь от результатов этих действий.
- Dlr обрабатывает случай автоматического вызова возврата делегата функцией, это также позволит вам сделать то же самое с FSharpFunc
Добавляет!? Префиксный оператор для обработки вызова динамических объектов и функций, которые не имеют тип во время выполнения.
Это открытый исходный код, лицензия Apache, вы можете посмотреть на реализацию, и она включает в себя примеры модульных тестов.
Вы никогда не сможете получить полностью общую реализацию ?
оператор. Оператор может быть реализован по-разному для различных типов, где может потребоваться сделать что-то особенное в зависимости от типа:
- За
Dictionary<T, R>
, вы хотите, чтобы он использовал функцию поиска в словаре - Для объектов SQL в моей статье, на которую вы ссылались, вы хотите, чтобы она использовала определенный API SQL
- Для неизвестных объектов.NET вы хотите использовать.NET Reflection
Если вы ищете реализацию, которая использует Reflection, то вы можете использовать ту, которую я реализовал в привязке F# для MonoDevelop ( доступна на GitHub). Он достаточно полон и обрабатывает доступ к свойствам, вызовы методов, а также статические члены. (Остальная часть связанного файла использует его для вызова внутренних членов компилятора F#). Он использует Reflection напрямую, поэтому он довольно медленный, но довольно полнофункциональный.
Другой альтернативой может быть реализация оператора поверх.NET 4.0 Dynamic Language Runtime (чтобы он использовал тот же базовый API, что и dynamic
в C# 4). Я не думаю, что есть реализация этого где-то там, но вот простой пример, как вы можете получить это:
#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
вызовы). I guess if you mixed the completeness (from the first one) with the approach to use DLR (in the second one), you'd get the most robust implementation you can get.
EDIT: I also posted the code to F# Snippets. Here is the version using DLR: http://fssnip.net/2U and here is the version from F# plugin (using.NET Reflection): http://fssnip.net/2V