-
Notifications
You must be signed in to change notification settings - Fork 2
/
uRun.pas
98 lines (80 loc) · 2.34 KB
/
uRun.pas
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
unit uRun;
interface
procedure Run;
implementation
uses
RTTI, SysUtils;
type
TValues = array of TValue;
function TryConversion(Str: string; TypeKind: TTypeKind; out Value: TValue): Boolean;
begin
Result := False;
case TypeKind of
tkInteger: begin
var Int: Integer;
Result := TryStrToInt(Str, Int);
Value := Int;
end;
tkChar: begin
Result := (Length(Str) = 1);
Value := Str[1];
end;
tkFloat: begin
var Ext: Extended;
Result := TryStrToFloat(Str, Ext);
Value := Ext;
end;
tkUString: begin
Value := Str;
Result := True;
end
else
Writeln('Unsupported TTypeKind: ', Ord(TypeKind));
end;
end;
procedure Run;
begin
// E.g. <UnitName>.<ClassName>.<MethodName>
var FullyQualifiedMethodName := ParamStr(1);
var Names := FullyQualifiedMethodName.Split(['.']);
// Note that unit names may contain dots.
if Length(Names) < 3 then
raise Exception.Create('Fully Qualified Method Name is Required.');
var UnitName := Names[0];
var ClassName := Names[1];
var MethodName := Names[2];
var Context := TRttiContext.Create;
var QualifiedTypeName := UnitName +'.'+ ClassName;
var InstType := Context.FindType(QualifiedTypeName) as TRttiInstanceType;
if not Assigned(InstType) then begin
raise Exception.Create('Unknown class: ' + ClassName);
end;
if not InstType.IsInstance then begin
raise Exception.Create(
'Unsupported Type. ' + ClassName + ' Only Instantiable Types Allowed.');
end;
var Method := InstType.GetMethod(MethodName);
var Arguments: TValues := [];
for var Parameter in Method.GetParameters do begin
var Str: string;
if not FindCmdLineSwitch(Parameter.Name, Str) then begin
raise Exception.Create(
'Expected Argument is missing from command line: ' + Parameter.ToString);
end;
var Value: TValue;
// Explicit conversion is necessary to avoid variant conversion issues.
if not TryConversion(Str, Parameter.ParamType.TypeKind, Value) then begin
raise Exception.Create('Unable to convert arguement, "' + Str
+ '", to the expected parameter type: ' + Parameter.ToString);
end;
Arguments := Arguments + [Value];
end;
try
Method.Invoke(InstType.MetaclassType, Arguments);
except
on E: Exception do
Writeln(E.Message);
end;
Context.Free;
end;
end.