34 people like it.
Like the snippet!
Dynamic operator using Dynamic Language Runtime
The snippet shows a simple implementation of the dynamic operator (?) that uses Dynamic Language Runtime and the C# implementation of dynamic operations. The snippet shows how to invoke instance methods with single argument.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
|
// Rreference C# implementation of dynamic operations
#r "Microsoft.CSharp.dll"
open System
open System.Runtime.CompilerServices
open Microsoft.CSharp.RuntimeBinder
// Simple implementation of ? operator that works for instance
// method calls that take a single argument and return some result
let (?) (inst:obj) name (arg:'T) : 'R =
// TODO: For efficient implementation, consider caching of call sites
// Create dynamic call site for converting result to type 'R
let convertSite =
CallSite<Func<CallSite, Object, 'R>>.Create
(Binder.Convert(CSharpBinderFlags.None, typeof<'R>, null))
// Create call site for performing call to method with the given
// name and a single parameter 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 call using second call site and then
// convert the result to the specified type using first call site
convertSite.Target.Invoke
(convertSite, callSite.Target.Invoke(callSite, inst, arg))
|
1:
2:
3:
|
// Dynamically invoke 'Next' method of 'Random' type
let o = box (new Random())
let a : int = o?Next(10)
|
namespace System
namespace System.Runtime
namespace System.Runtime.CompilerServices
namespace Microsoft
namespace Microsoft.CSharp
namespace Microsoft.CSharp.RuntimeBinder
val inst : obj
type obj = Object
Full name: Microsoft.FSharp.Core.obj
val name : string
val arg : 'T
val convertSite : CallSite<Func<CallSite,Object,'R>>
Multiple items
type CallSite =
member Binder : CallSiteBinder
static member Create : delegateType:Type * binder:CallSiteBinder -> CallSite
Full name: System.Runtime.CompilerServices.CallSite
--------------------
type CallSite<'T (requires reference type)> =
inherit CallSite
val Target : 'T
member Update : 'T
static member Create : binder:CallSiteBinder -> CallSite<'T>
Full name: System.Runtime.CompilerServices.CallSite<_>
Multiple items
type Func<'TResult> =
delegate of unit -> 'TResult
Full name: System.Func<_>
--------------------
type Func<'T,'TResult> =
delegate of 'T -> 'TResult
Full name: System.Func<_,_>
--------------------
type Func<'T1,'T2,'TResult> =
delegate of 'T1 * 'T2 -> 'TResult
Full name: System.Func<_,_,_>
--------------------
type Func<'T1,'T2,'T3,'TResult> =
delegate of 'T1 * 'T2 * 'T3 -> 'TResult
Full name: System.Func<_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 -> 'TResult
Full name: System.Func<_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 -> 'TResult
Full name: System.Func<_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>
--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'T16,'TResult> =
delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 * 'T16 -> 'TResult
Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>
Multiple items
type Object =
new : unit -> obj
member Equals : obj:obj -> bool
member GetHashCode : unit -> int
member GetType : unit -> Type
member ToString : unit -> string
static member Equals : objA:obj * objB:obj -> bool
static member ReferenceEquals : objA:obj * objB:obj -> bool
Full name: System.Object
--------------------
Object() : unit
type Binder =
static member BinaryOperation : flags:CSharpBinderFlags * operation:ExpressionType * context:Type * argumentInfo:IEnumerable<CSharpArgumentInfo> -> CallSiteBinder
static member Convert : flags:CSharpBinderFlags * type:Type * context:Type -> CallSiteBinder
static member GetIndex : flags:CSharpBinderFlags * context:Type * argumentInfo:IEnumerable<CSharpArgumentInfo> -> CallSiteBinder
static member GetMember : flags:CSharpBinderFlags * name:string * context:Type * argumentInfo:IEnumerable<CSharpArgumentInfo> -> CallSiteBinder
static member Invoke : flags:CSharpBinderFlags * context:Type * argumentInfo:IEnumerable<CSharpArgumentInfo> -> CallSiteBinder
static member InvokeConstructor : flags:CSharpBinderFlags * context:Type * argumentInfo:IEnumerable<CSharpArgumentInfo> -> CallSiteBinder
static member InvokeMember : flags:CSharpBinderFlags * name:string * typeArguments:IEnumerable<Type> * context:Type * argumentInfo:IEnumerable<CSharpArgumentInfo> -> CallSiteBinder
static member IsEvent : flags:CSharpBinderFlags * name:string * context:Type -> CallSiteBinder
static member SetIndex : flags:CSharpBinderFlags * context:Type * argumentInfo:IEnumerable<CSharpArgumentInfo> -> CallSiteBinder
static member SetMember : flags:CSharpBinderFlags * name:string * context:Type * argumentInfo:IEnumerable<CSharpArgumentInfo> -> CallSiteBinder
...
Full name: Microsoft.CSharp.RuntimeBinder.Binder
Binder.Convert(flags: CSharpBinderFlags, type: Type, context: Type) : CallSiteBinder
type CSharpBinderFlags =
| None = 0
| CheckedContext = 1
| InvokeSimpleName = 2
| InvokeSpecialName = 4
| BinaryOperationLogical = 8
| ConvertExplicit = 16
| ConvertArrayIndex = 32
| ResultIndexed = 64
| ValueFromCompoundAssignment = 128
| ResultDiscarded = 256
Full name: Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags
field CSharpBinderFlags.None = 0
val typeof<'T> : Type
Full name: Microsoft.FSharp.Core.Operators.typeof
val callSite : CallSite<Func<CallSite,Object,'T,Object>>
Binder.InvokeMember(flags: CSharpBinderFlags, name: string, typeArguments: Collections.Generic.IEnumerable<Type>, context: Type, argumentInfo: Collections.Generic.IEnumerable<CSharpArgumentInfo>) : CallSiteBinder
type CSharpArgumentInfo =
static member Create : flags:CSharpArgumentInfoFlags * name:string -> CSharpArgumentInfo
Full name: Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
CSharpArgumentInfo.Create(flags: CSharpArgumentInfoFlags, name: string) : CSharpArgumentInfo
type CSharpArgumentInfoFlags =
| None = 0
| UseCompileTimeType = 1
| Constant = 2
| NamedArgument = 4
| IsRef = 8
| IsOut = 16
| IsStaticType = 32
Full name: Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags
field CSharpArgumentInfoFlags.None = 0
field CallSite.Target
Func.Invoke(arg1: CallSite, arg2: Object) : 'R
Func.Invoke(arg1: CallSite, arg2: Object, arg3: 'T) : Object
val o : obj
Full name: Script.o
val box : value:'T -> obj
Full name: Microsoft.FSharp.Core.Operators.box
Multiple items
type Random =
new : unit -> Random + 1 overload
member Next : unit -> int + 2 overloads
member NextBytes : buffer:byte[] -> unit
member NextDouble : unit -> float
Full name: System.Random
--------------------
Random() : unit
Random(Seed: int) : unit
val a : int
Full name: Script.a
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
More information