1 
2 module witchcraft.invocable;
3 
4 import witchcraft;
5 
6 import std.variant;
7 
8 interface Invocable : Member
9 {
10     /++
11      + Returns an array of `Type` objects representing this element's
12      + parameter types. If a parameter does not have an associated reflective
13      + type, its value is `null`.
14      +
15      + Returns:
16      +   This element's parameter types.
17      +
18      + See_Also:
19      +   getParameterTypes
20      ++/
21     const(Type)[] getParameterTypes() const;
22 
23     /++
24      + Returns an array representing the element's parameter types.
25      +
26      + Returns:
27      +   This method's parameter types.
28      ++/
29     const(TypeInfo)[] getParameterTypeInfos() const;
30 
31     /++
32      + A `Type` object that represent's this element's return type, if type
33      + type has reflective support. Null is returned otherwise.
34      +
35      + Returns:
36      +   This element's return type.
37      ++/
38     @property
39     const(Type) getReturnType() const;
40 
41     /++
42      + This element's return `TypeInfo` object.
43      +
44      + Returns:
45      +   This element's return type.
46      ++/
47     @property
48     const(TypeInfo) getReturnTypeInfo() const;
49 
50     /++
51      + Invokes this element on the given instance of class using arguments given
52      + as an array of `Variant` values. For static elements, the value of the
53      + instance object may be null.
54      + The result is returned as a `Variant`. If the call would return void,
55      + a null value is returned instead.
56      +
57      + Params:
58      +   instance  = The object instance to invoke the method as.
59      +   arguments = The arguments to be passed along to the method.
60      +
61      + Returns:
62      +   The result of the invocation.
63      ++/
64     Variant invoke(Variant instance, Variant[] arguments...) const;
65 
66     /++
67      + Ditto, but arguments are taken as variadic arguments.
68      + A template argument may be specified to covert the result of the call.
69      +
70      + Params:
71      +   T         = The type to convert the result into.
72      +   instance  = The object instance to invoke the method as.
73      +   arguments = The arguments to be passed along to the method.
74      +
75      + Returns:
76      +   The result of the invocation.
77      ++/
78     final T invoke(T = Variant, O, TList...)(O instance, TList arguments) const
79     {
80         auto values = new Variant[TList.length];
81 
82         foreach(index, argument; arguments)
83         {
84             values[index] = Variant(argument);
85         }
86 
87         static if(is(O == interface)) {
88             auto result = this.invoke(Variant(cast(Object)instance), values);
89         } else {
90             auto result = this.invoke(Variant(instance), values);
91         }
92 
93         static if(is(T == Variant))
94         {
95             return result;
96         }
97         else
98         {
99             return result.get!T;
100         }
101     }
102 
103     /++
104      + Checks if this element accepts variable arguments.
105      +
106      + Returns:
107      +   `true` if the element accepts varargs.
108      ++/
109     @property
110     bool isVarArgs() const;
111 }