RTTI(D2010バージョン14.0.3593.25826を実行中)で取得したコンストラクタを呼び出そうとしています。コンストラクタは文字列とオブジェクトの引数を引数として取ります。これらの引数はすべて''
またはnil
に初期化する必要があります。 (免責事項:私は希望のコンストラクタは、パラメータの最大数、したがって、奇妙に見える、けれども次善のデザインのいずれかになりますことを知っている)、次のようにDelphi:invokeコンストラクタがEInvalidCastを生成します
コードが行く:
program sb_rtti;
{$APPTYPE CONSOLE}
uses RTTI, TypInfo, SysUtils;
type
TMyClass = class (TObject)
FField1: string;
FObject1: TObject;
public
constructor Create(Field1: string = ''; Object1: TObject = nil);
end;
constructor TMyClass.Create(Field1: string; Object1: TObject);
begin
FField1 := Field1;
FObject1 := Object1;
end;
function GetConstructor(rType: TRttiType) : TRttiMethod;
var
MaxParams: integer;
Methods: TArray<TRttiMethod>;
Method: TRttiMethod;
Params: TArray<TRttiParameter>;
begin
Methods := rType.GetMethods('Create');
MaxParams := 0;
for Method in Methods do begin
Params := Method.GetParameters();
if (Length(Params) > MaxParams) then begin
Result := Method;
MaxParams := Length(Params);
end;
end;
end;
procedure InitializeParam(Param: TRttiParameter; ActualParam: TValue);
begin
if (Param.ParamType.TypeKind = TTypeKind.tkClass) then begin
ActualParam := TValue.From<TObject>(nil);
end else if (Param.ParamType.TypeKind = TTypeKind.tkString) then begin
ActualParam := TValue.From<string>('');
end else if (Param.ParamType.TypeKind = TTypeKind.tkUString) then begin
ActualParam := TValue.From<UnicodeString>('');
end else begin
// Other types goes here
end;
end;
var
Context: TRttiContext;
Constr: TRttiMethod;
Params: TArray<TRttiParameter>;
ResultValue: TValue;
rType: TRttiType;
ActualParams: array of TValue;
i: integer;
CurrentParam: TRttiParameter;
begin
Context := TRttiContext.Create();
rType := Context.GetType(TypeInfo(TMyClass));
Constr := GetConstructor(rType);
try
if (Constr <> nil) then begin
Params := Constr.GetParameters();
SetLength(ActualParams, Length(Params));
for i := 0 to Length(Params) - 1 do begin
CurrentParam := Params[i] as TRttiParameter;
InitializeParam(CurrentParam, ActualParams[i]);
end;
ResultValue := Constr.Invoke(rType.AsInstance.MetaclassType, ActualParams);
end;
except
on E : Exception do
WriteLn(E.ToString);
end;
ReadLn;
end.
を今、とき行ResultValue := Constr.Invoke(rType.AsInstance.MetaclassType, ActualParams);
が実行され、EInvalidCast例外が発生します。例外は、(argList[currArg] := Args[i].Cast(parList[i].ParamType.Handle);
)rtti.pasにライン4093でより正確に、しかし、問題の肉は、コールスタック内の前の時点で見出されると思われる線1336
でTValue.Cast
-methodに追跡することができます。
私は、私が想定していない方法でrttiを使用していますが、どこでも記述された「正しい方法」を見つけることはできません。誰かが私を正しい方向に向けることができますか?ありがとう!
ありがとうございました、私はちょうど私に起きました...私は参照渡しと値渡しのルールを混ぜています。 :)私は、私の心は、 "それはrttiに関連していなければならなかった"というアイデアにとても固定されていると思うので、私は基本を忘れてしまった。 – conciliator