Delphiのクラスメソッドをクラス名とメソッド名を文字列で指定して実行する。
unit Unit1;
interface
type
TMyClass = class
public
// 引数のないクラスメソッド
class procedure TestFunc1; static;
// 引数のあるクラスメソッド
class procedure TestFunc2(const S: string); static;
end;
というユニットがあって、このUnit1のTMyClassのクラスメソッドを、次のようにクラス名とメソッド名を文字列で指定して実行する関数を作る。
InvokeStatic('Unit1.TMyClass', 'TestFunc1', []);
InvokeStatic('Unit1.TMyClass', 'TestFunc2', ['Test2']);
実装は次のようになる。
uses System.Rtti, System.TypInfo;
/// <summary>
/// クラスメソッドを実行する
/// </summary>
/// <param name="AClassName">
/// ユニット名.クラス名
/// </param>
/// <param name="AMetohdName">
/// メソッド名
/// </param>
/// <param name="Args">
/// メソッドの引数
/// </param>
procedure InvokeStatic(const AClassName, AMetohdName: string;
const Args: array of TValue);
var
RttiContext: TRttiContext;
RttiType: TRttiType;
Instance: TRttiInstanceType;
Method: TRttiMethod;
begin
// 「ユニット名.クラス名」から型を取得する
RttiType := RttiContext.FindType(AClassName);
// 取得した型がクラス型がどうか
if (RttiType <> nil) and (RttiType.TypeKind = tkClass) then
begin
// TRttiInstanceTypeインスタンスにキャストする
Instance := RttiType.AsInstance;
// メソッド名からメソッドのRTTIオブジェクトを取得する
Method := Instance.GetMethod(AMetohdName);
// メソッドを実行する
Method.Invoke(Instance, Args);
end;
end;
プログラムの中でTMyClassが使用されていない場合は、コンパイル時の最適化によってTMyClassが削除されるため、TMyClassを使用するコードを含める必要がある。
Delphi XE6で確認しました。