Reputation: 329
I'm trying to create some kind of interface, but i cannot find how to use custom attributes in F# as MSDN only shows usage of CLR attributes. This is what i want to achieve:
open System
type Command (name : string) =
inherit Attribute()
member this.Name = name
[<Command("something")>]
let doSomething () =
Console.Write("I'm doing something")
[<Command("somethingElse")>]
let doSomethingElse () =
Console.Write("I'm doing something else")
[<EntryPoint>]
let main args =
let command = Console.ReadLine()
// find function where Command.Name = command and call it
Console.Read()
0
Upvotes: 2
Views: 937
Reputation: 13577
To extend on your answer, a more generic approach would be to get all the types and then filter the functions that have the attribute you're looking for (as your approach would break down once your application grows and no longer has everything "packed" into the Program class):
let getCommands () =
let types = Assembly.GetExecutingAssembly().GetTypes()
let commands =
types
|> Array.collect (fun typ -> typ.GetMethods())
|> Array.choose (fun mi ->
mi.CustomAttributes
|> Seq.tryFind (fun attr -> attr.AttributeType = typeof<Command>)
|> Option.map (fun attr -> attr, mi))
let commandsMap =
commands
|> Seq.map (fun (attr, mi) ->
let name =
let arg = attr.ConstructorArguments.[0]
unbox<string> arg.Value
name, mi)
|> Map.ofSeq
commandsMap
This gets all the functions from all the types in the executing assembly, then filters out everything that doesn't have command attribute. Then it builds a map where the key is the attribute argument and the value is the MethodInfo
of the function.
Upvotes: 4
Reputation: 329
Ok, found it.
Reflection.Assembly.GetExecutingAssembly().GetType("Program").GetMethods()
Program
typename is not viable in code so it cannot be used in typeof<Program>
, but this type exists and can be taken from assembly.
Upvotes: 0