3

カスタムクラスからxmlへのコンバーターを使用していますが、要件の1つはTObjectList<T>フィールドをストリーミングする機能です。TObjectlistのオブジェクトを取得するため
にメソッドを呼び出そうとしていますが、タイプが明らかに一致しないため、「Invalidclasstypecast」が表示されます。ToArray()

このクラスを例にとってみましょう。

type
  TSite = class
    Name : String;
    Address : String; 
  end;

  TSites = class
    Sites : TObjecList<TSite>;
  end;  

SitesTObjectListからSiteObjectsを取得する必要があります。私はRTTIを使用しているので、TObjectListのObjectTypeがわからないため、型キャストは機能しないことに注意してください。これは私が持っているものですが、行き止まりのようです(ObjはTobjectList<TSite>ここにあります):

function TXmlPersister.ObjectListToXml(Obj : TObject; Indent: String): String;

var
  TypInfo: TRttiType;
  meth: TRttiMethod;
  Arr  : TArray<TObject>;

begin
 Result := '';
 TypInfo := ctx.GetType(Obj.ClassInfo);
 Meth := TypInfo.GetMethod('ToArray');
 if Assigned(Meth) then
  begin
   Arr := Invoke(Obj, []).AsType<TArray<TObject>>; // invalid class typecast error

   if Length(Arr) > 0 then
    begin
     // get objects from array and stream them
     ...
    end;
  end;

RTTIを介してTObjectListからオブジェクトを取得する方法は、私にとっては良いことです。奇妙な理由で、TypInfoにGetItem/SetItemメソッドが表示されません

編集

デビッドのおかげで私は私の解決策を持っています:

function TXmlPersister.ObjectListToXml(Obj : TObject; Indent: String): String;

var
  TypInfo: TRttiType;
  meth: TRttiMethod;
  Value: TValue;
  Count : Integer;

begin
 Result := '';
 TypInfo := ctx.GetType(Obj.ClassInfo);
 Meth := TypInfo.GetMethod('ToArray');
 if Assigned(Meth) then
  begin
   Value := Meth.Invoke(Obj, []);
   Assert(Value.IsArray);
   Count :=  Value.GetArrayLength;
   while Count > 0 do
    begin
     Dec(Count);
     Result := Result + ObjectToXml(Value.GetArrayElement(Count).AsObject, Indent);
    end;
  end;
end;

私は提案を受け入れています、多分この目標を達成するためのより多くの「賢い」方法があります...

4

1 に答える 1

4

動的配列はTObjectではないため、コードは失敗します。

あなたはこのようにそれを行うことができます:

Value := Meth.Invoke(Obj, []);
Assert(Value.IsArray);
SetLength(Arr, Value.GetArrayLength);
for i := 0 to Length(Arr)-1 do
  Arr[i] := Value.GetArrayElement(i).AsObject;
于 2012-09-19T15:59:36.630 に答える