三、解決問題
通過以上問題的分析,我們可以很容易的寫出兩個函數
1、GetParams:獲取方法所包含的參數信息集合
2、GetReturnInfo:獲取方法的返回參數信息
代碼如下:
uses
SysUtils,
StrUtils,
TypInfo,
ObjAuto;
type
TParamInfoArray = array of PParamInfo;
function GetParams(aObj: TObject; aMethodName: string): TParamInfoArray;
function GetReturnInfo(aObj: TObject; aMethodName: string): PReturnInfo;
implementation
const
SHORT_LEN = SizeOf(ShortString) - 1;
function GetReturnInfo(aObj: TObject; aMethodName: string): PReturnInfo;
var
mi: PMethodInfoHeader;
begin
// 獲取函數頭指針並判斷是否合法
mi := ObjAuto.GetMethodInfo(aObj, ShortString(aMethodName));
if mi.Len <= SizeOf(TMethodInfoHeader) + Length(mi.Name) - SHORT_LEN then
Exit(nil);
Result := PReturnInfo(Integer(mi) + SizeOf(TMethodInfoHeader) +
Length(mi.Name) - SHORT_LEN);
end;
function GetParams(aObj: TObject; aMethodName: string): TParamInfoArray;
var
mi: PMethodInfoHeader;
mIEnd: Pointer;
param: PParamInfo;
count: Integer;
begin
// 初始化返回值
SetLength(Result, 0);
// 獲取函數頭指針並判斷是否合法
mi := ObjAuto.GetMethodInfo(aObj, ShortString(aMethodName));
if mi.Len <= SizeOf(TMethodInfoHeader) + Length(mi.Name) - SHORT_LEN then
Exit;
// 獲取函數尾地址用於遍歷
mIEnd := Pointer(Integer(mi) + mi.Len);
// 第一個參數的地址根據以下算法得來
param := PParamInfo(Integer(mi) + SizeOf(TMethodInfoHeader) +
Length(mi.Name) - SHORT_LEN + SizeOf(TReturnInfo));
count := 0;
// 判斷遍歷是否超過了函數尾地址
while Integer(param) < Integer(mIEnd) do
begin
Inc(count);
SetLength(Result, count);
Result[count - 1] := param;
// 往後的參數地址算法由來
param := PParamInfo(Integer(param) + SizeOf(TParamInfo) +
Length(param.Name) - SHORT_LEN);
end;
end;