Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a1e86c1

Browse files
authored
Delegate F# snippets (#7606)
1 parent de0b1d8 commit a1e86c1

File tree

9 files changed

+392
-0
lines changed

9 files changed

+392
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net6.0</TargetFramework>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<Compile Include="openClosedOver.fs" />
8+
<Compile Include="source1.fs" />
9+
<Compile Include="source.fs" />
10+
</ItemGroup>
11+
</Project>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
module openClosedOver
2+
3+
// All four permutations of instance/static with open/closed.
4+
//
5+
//<Snippet1>
6+
open System
7+
open System.Reflection
8+
9+
// A sample class with an instance method and a static method.
10+
type C(id) =
11+
member _.M1(s) =
12+
printfn $"Instance method M1 on C: id = %i{id}, s = %s{s}"
13+
14+
static member M2(s) =
15+
printfn $"Static method M2 on C: s = %s{s}"
16+
17+
// Declare three delegate types for demonstrating the combinations
18+
// of static versus instance methods and open versus closed
19+
// delegates.
20+
type D1 = delegate of C * string -> unit
21+
type D2 = delegate of string -> unit
22+
type D3 = delegate of unit -> unit
23+
24+
let c1 = C 42
25+
26+
// Get a MethodInfo for each method.
27+
//
28+
let mi1 = typeof<C>.GetMethod("M1", BindingFlags.Public ||| BindingFlags.Instance)
29+
let mi2 = typeof<C>.GetMethod("M2", BindingFlags.Public ||| BindingFlags.Static)
30+
31+
printfn "\nAn instance method closed over C."
32+
33+
// In this case, the delegate and the
34+
// method must have the same list of argument types use
35+
// delegate type D2 with instance method M1.
36+
let test = Delegate.CreateDelegate(typeof<D2>, c1, mi1, false)
37+
38+
// Because false was specified for throwOnBindFailure
39+
// in the call to CreateDelegate, the variable 'test'
40+
// contains null if the method fails to bind (for
41+
// example, if mi1 happened to represent a method of
42+
// some class other than C).
43+
if test <> null then
44+
let d2 = test :?> D2
45+
46+
// The same instance of C is used every time the
47+
// delegate is invoked.
48+
d2.Invoke "Hello, World!"
49+
d2.Invoke "Hi, Mom!"
50+
51+
printfn "\nAn open instance method."
52+
53+
// In this case, the delegate has one more
54+
// argument than the instance method this argument comes
55+
// at the beginning, and represents the hidden instance
56+
// argument of the instance method. Use delegate type D1
57+
// with instance method M1.
58+
let d1 = Delegate.CreateDelegate(typeof<D1>, null, mi1) :?> D1
59+
60+
// An instance of C must be passed in each time the
61+
// delegate is invoked.
62+
d1.Invoke(c1, "Hello, World!")
63+
d1.Invoke(C 5280, "Hi, Mom!")
64+
65+
printfn "\nAn open static method."
66+
// In this case, the delegate and the method must
67+
// have the same list of argument types use delegate type
68+
// D2 with static method M2.
69+
let d2 = Delegate.CreateDelegate(typeof<D2>, null, mi2) :?> D2
70+
71+
// No instances of C are involved, because this is a static
72+
// method.
73+
d2.Invoke "Hello, World!"
74+
d2.Invoke "Hi, Mom!"
75+
76+
printfn "\nA static method closed over the first argument (String)."
77+
// The delegate must omit the first argument of the method.
78+
// A string is passed as the firstArgument parameter, and
79+
// the delegate is bound to this string. Use delegate type
80+
// D3 with static method M2.
81+
let d3 = Delegate.CreateDelegate(typeof<D3>, "Hello, World!", mi2) :?> D3
82+
83+
// Each time the delegate is invoked, the same string is used.
84+
d3.Invoke()
85+
86+
// This code example produces the following output:
87+
// An instance method closed over C.
88+
// Instance method M1 on C: id = 42, s = Hello, World!
89+
// Instance method M1 on C: id = 42, s = Hi, Mom!
90+
//
91+
// An open instance method.
92+
// Instance method M1 on C: id = 42, s = Hello, World!
93+
// Instance method M1 on C: id = 5280, s = Hi, Mom!
94+
//
95+
// An open static method.
96+
// Static method M2 on C: s = Hello, World!
97+
// Static method M2 on C: s = Hi, Mom!
98+
//
99+
// A static method closed over the first argument (String).
100+
// Static method M2 on C: s = Hello, World!
101+
//</Snippet1>
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
module source
2+
3+
// Showing all the things D(A) can bind to.
4+
//<Snippet1>
5+
open System
6+
7+
// Declare two sample classes, C and F. Class C has an ID
8+
// property so instances can be identified.
9+
type C(id) =
10+
member _.ID = id
11+
12+
member _.M1(c: C) =
13+
printfn $"Instance method M1(C c) on C: this.id = {id}, c.ID = {c.ID}"
14+
15+
member _.M2() =
16+
printfn $"Instance method M2() on C: this.id = {id}"
17+
18+
static member M3(c: C) =
19+
printfn $"Static method M3(C c) on C: c.ID = {c.ID}"
20+
21+
static member M4(c1: C, c2: C) =
22+
printfn $"Static method M4(C c1, C c2) on C: c1.ID = {c1.ID}, c2.ID = {c2.ID}"
23+
24+
// Declare a delegate type. The object of this code example
25+
// is to show all the methods this delegate can bind to.
26+
type D = delegate of C -> unit
27+
28+
29+
type F() =
30+
member _.M1(c: C) =
31+
printfn $"Instance method M1(C c) on F: c.ID = {c.ID}"
32+
33+
member _.M3(c: C) =
34+
printfn $"Static method M3(C c) on F: c.ID = {c.ID}"
35+
36+
member _.M4(f: F, c: C) =
37+
printfn $"Static method M4(F f, C c) on F: c.ID = {c.ID}"
38+
39+
[<EntryPoint>]
40+
let main _ =
41+
let c1 = C 42
42+
let c2 = C 1491
43+
let f1 = F()
44+
45+
// Instance method with one argument of type C.
46+
let cmi1 = typeof<C>.GetMethod "M1"
47+
// Instance method with no arguments.
48+
let cmi2 = typeof<C>.GetMethod "M2"
49+
// Static method with one argument of type C.
50+
let cmi3 = typeof<C>.GetMethod "M3"
51+
// Static method with two arguments of type C.
52+
let cmi4 = typeof<C>.GetMethod "M4"
53+
54+
// Instance method with one argument of type C.
55+
let fmi1 = typeof<F>.GetMethod "M1"
56+
// Static method with one argument of type C.
57+
let fmi3 = typeof<F>.GetMethod "M3"
58+
// Static method with an argument of type F and an argument
59+
// of type C.
60+
let fmi4 = typeof<F>.GetMethod "M4"
61+
62+
printfn "\nAn instance method on any type, with an argument of type C."
63+
// D can represent any instance method that exactly matches its
64+
// signature. Methods on C and F are shown here.
65+
let d = Delegate.CreateDelegate(typeof<D>, c1, cmi1) :?> D
66+
d.Invoke c2
67+
let d = Delegate.CreateDelegate(typeof<D>, f1, fmi1) :?> D
68+
d.Invoke c2
69+
70+
Console.WriteLine("\nAn instance method on C with no arguments.")
71+
// D can represent an instance method on C that has no arguments
72+
// in this case, the argument of D represents the hidden first
73+
// argument of any instance method. The delegate acts like a
74+
// static method, and an instance of C must be passed each time
75+
// it is invoked.
76+
let d = Delegate.CreateDelegate(typeof<D>, null, cmi2) :?> D
77+
d.Invoke c1
78+
79+
printfn "\nA static method on any type, with an argument of type C."
80+
// D can represent any static method with the same signature.
81+
// Methods on F and C are shown here.
82+
let d = Delegate.CreateDelegate(typeof<D>, null, cmi3) :?> D
83+
d.Invoke c1
84+
let d = Delegate.CreateDelegate(typeof<D>, null, fmi3) :?> D
85+
d.Invoke c1
86+
87+
printfn "\nA static method on any type, with an argument of"
88+
printfn " that type and an argument of type C."
89+
// D can represent any static method with one argument of the
90+
// type the method belongs and a second argument of type C.
91+
// In this case, the method is closed over the instance of
92+
// supplied for the its first argument, and acts like an instance
93+
// method. Methods on F and C are shown here.
94+
let d = Delegate.CreateDelegate(typeof<D>, c1, cmi4) :?> D
95+
d.Invoke c2
96+
let test =
97+
Delegate.CreateDelegate(typeof<D>, f1, fmi4, false)
98+
99+
// This final example specifies false for throwOnBindFailure
100+
// in the call to CreateDelegate, so the variable 'test'
101+
// contains Nothing if the method fails to bind (for
102+
// example, if fmi4 happened to represent a method of
103+
// some class other than F).
104+
match test with
105+
| :? D as d ->
106+
d.Invoke c2
107+
| _ -> ()
108+
0
109+
110+
// This code example produces the following output:
111+
// An instance method on any type, with an argument of type C.
112+
// Instance method M1(C c) on C: this.id = 42, c.ID = 1491
113+
// Instance method M1(C c) on F: c.ID = 1491
114+
//
115+
// An instance method on C with no arguments.
116+
// Instance method M2() on C: this.id = 42
117+
//
118+
// A static method on any type, with an argument of type C.
119+
// Static method M3(C c) on C: c.ID = 42
120+
// Static method M3(C c) on F: c.ID = 42
121+
//
122+
// A static method on any type, with an argument of
123+
// that type and an argument of type C.
124+
// Static method M4(C c1, C c2) on C: c1.ID = 42, c2.ID = 1491
125+
// Static method M4(F f, C c) on F: c.ID = 1491
126+
//</Snippet1>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module source1
2+
3+
// <Snippet1>
4+
open System
5+
open System.Reflection
6+
7+
// Define two classes to use in the demonstration, a base class and
8+
// a class that derives from it.
9+
type Base() = class end
10+
11+
type Derived() =
12+
inherit Base()
13+
14+
// Define a static method to use in the demonstration. The method
15+
// takes an instance of Base and returns an instance of Derived.
16+
// For the purposes of the demonstration, it is not necessary for
17+
// the method to do anything useful.
18+
static member MyMethod(arg: Base) =
19+
Derived()
20+
21+
// Define a delegate that takes an instance of Derived and returns an
22+
// instance of Base.
23+
type Example = delegate of Derived -> Base
24+
25+
// The binding flags needed to retrieve MyMethod.
26+
let flags = BindingFlags.Public ||| BindingFlags.Static
27+
28+
// Get a MethodInfo that represents MyMethod.
29+
let minfo = typeof<Derived>.GetMethod("MyMethod", flags)
30+
31+
// Demonstrate contravariance of parameter types and covariance
32+
// of return types by using the delegate Example to represent
33+
// MyMethod. The delegate binds to the method because the
34+
// parameter of the delegate is more restrictive than the
35+
// parameter of the method (that is, the delegate accepts an
36+
// instance of Derived, which can always be safely passed to
37+
// a parameter of type Base), and the return type of MyMethod
38+
// is more restrictive than the return type of Example (that
39+
// is, the method returns an instance of Derived, which can
40+
// always be safely cast to type Base).
41+
let ex = Delegate.CreateDelegate(typeof<Example>, minfo) :?> Example
42+
43+
// Execute MyMethod using the delegate Example.
44+
let b = Derived() |> ex.Invoke
45+
// </Snippet1>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net6.0</TargetFramework>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<Compile Include="source.fs" />
8+
</ItemGroup>
9+
</Project>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// <Snippet1>
2+
// Declares a delegate for a method that takes in an int and returns a string.
3+
type MyMethodDelegate = delegate of int -> string
4+
5+
// Defines some methods to which the delegate can point.
6+
type MySampleClass() =
7+
// Defines an instance method.
8+
member _.MyStringMethod(myInt) =
9+
if myInt > 0 then "positive"
10+
elif myInt < 0 then "negative"
11+
else "zero"
12+
13+
// Defines a static method.
14+
static member MySignMethod(myInt) =
15+
if myInt > 0 then "+"
16+
elif myInt < 0 then "-"
17+
else ""
18+
19+
// Creates one delegate for each method. For the instance method, an
20+
// instance (mySC) must be supplied. For the static method, use the
21+
// class name.
22+
let mySC = MySampleClass()
23+
let myD1 = MyMethodDelegate mySC.MyStringMethod
24+
let myD2 = MyMethodDelegate MySampleClass.MySignMethod
25+
26+
// Invokes the delegates.
27+
printfn $"{5} is {myD1.Invoke 5} use the sign \"{myD2.Invoke 5}\"."
28+
printfn $"{-3} is {myD1.Invoke -3} use the sign \"{myD2.Invoke -3}\"."
29+
printfn $"{0} is {myD1.Invoke 0} use the sign \"{myD2.Invoke 0}\"."
30+
31+
// This code produces the following output:
32+
// 5 is positive use the sign "+".
33+
// -3 is negative use the sign "-".
34+
// 0 is zero use the sign "".
35+
// </Snippet1>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// <Snippet1>
2+
open System
3+
open System.IO
4+
open System.Reflection
5+
open System.Windows.Forms
6+
7+
let outputToFile (s: string) =
8+
use sw = new StreamWriter(@".\output.txt")
9+
sw.WriteLine s
10+
11+
let showMessageBox s =
12+
MessageBox.Show s |> ignore
13+
14+
let outputMessage =
15+
Delegate.Combine(
16+
Action<string>(Console.WriteLine),
17+
Action<string>(outputToFile),
18+
Action<string>(showMessageBox))
19+
:?> Action<string>
20+
21+
printfn $"Invocation list has {outputMessage.GetInvocationList().Length} methods."
22+
23+
// Invoke delegates normally.
24+
outputMessage.Invoke "Hello there!"
25+
printfn "Press <Enter> to continue..."
26+
stdin.ReadLine() |> ignore
27+
28+
// Invoke each delegate in the invocation list in reverse order.
29+
for i = outputMessage.GetInvocationList().Length - 1 downto 0 do
30+
let outputMsg = outputMessage.GetInvocationList()[i]
31+
outputMsg.DynamicInvoke "Greetings and salutations!"
32+
|> ignore
33+
34+
printfn "Press <Enter> to continue..."
35+
stdin.ReadLine() |> ignore
36+
37+
// Invoke each delegate that doesn't write to a file.
38+
for i = 0 to outputMessage.GetInvocationList().Length - 1 do
39+
let outputMsg = outputMessage.GetInvocationList()[i]
40+
if not (outputMsg.GetMethodInfo().Name.Contains "File") then
41+
outputMsg.DynamicInvoke "Hi!"
42+
|> ignore
43+
// </Snippet1>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net6.0-windows</TargetFramework>
5+
<UseWindowsForms>true</UseWindowsForms>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<Compile Include="GetInvocationList1.fs" />
9+
</ItemGroup>
10+
</Project>

0 commit comments

Comments
 (0)